From b9a9fb2e56c0e9817481d875e6d30a2f22dbc65a Mon Sep 17 00:00:00 2001 From: Oleg Hasjanov Date: Tue, 12 Sep 2023 14:19:02 +0300 Subject: [PATCH] updated modal windows, added new views, config turbo frame --- app/assets/builds/application.css | 354 +- app/assets/builds/application.js | 11655 ++++++++-------- app/assets/builds/application.js.map | 8 +- .../stylesheets/components/_account.scss | 44 +- .../stylesheets/components/_address.scss | 82 + .../stylesheets/components/_components.scss | 4 + app/assets/stylesheets/components/_cta.scss | 14 + .../components/_table-whishlist.scss | 78 + .../stylesheets/components/_wishlist.scss | 16 + app/assets/stylesheets/objects/_grid.scss | 16 +- app/assets/stylesheets/tools/_mq.scss | 2 +- .../stylesheets/utilities/_flexbox.scss | 2 +- app/assets/stylesheets/utilities/_margin.scss | 7 +- .../auctions/update_list_broadcast_service.rb | 13 +- app/channels/notification_channel.rb | 13 - .../common/header/component.html.erb | 13 +- app/components/common/header/component.rb | 10 +- .../modals/change_offer/component.html.erb | 6 +- .../modals/change_offer_po/component.html.erb | 6 +- .../modals/delete_offer/component.html.erb | 10 +- .../modals/delete_offer/component.rb | 10 +- .../modals/deposit/component.html.erb | 6 +- .../modals/pay_invoice/component.html.erb | 4 +- .../modals/winner_domain/component.html.erb | 9 +- app/controllers/application_controller.rb | 3 +- .../billing_profiles_controller.rb | 58 +- app/controllers/concerns/offer_notifable.rb | 22 +- app/controllers/english_offers_controller.rb | 4 +- .../notifications/mark_as_read_controller.rb | 19 +- app/controllers/notifications_controller.rb | 8 +- app/controllers/offers_controller.rb | 25 +- app/controllers/wishlist_items_controller.rb | 82 +- app/javascript/application.js | 3 +- .../controllers/hamburger_controller.js | 14 + app/javascript/controllers/index.js | 5 +- .../modals/offer_modal_controller.js | 14 +- app/models/ability.rb | 1 + app/views/auctions/_auction.html.erb | 4 +- app/views/auctions/index.html.erb | 10 +- .../streams/updated_list.turbo_stream.erb | 19 +- .../billing_profiles/_billing_info.html.erb | 10 +- app/views/billing_profiles/_form.html.erb | 19 +- app/views/billing_profiles/_new_form.html.erb | 55 + app/views/billing_profiles/index.html.erb | 6 +- app/views/common/_flash.html.erb | 4 +- app/views/common/_webpush_modal.html.erb | 34 +- app/views/english_offers/edit.html.erb | 2 +- app/views/english_offers/new.html.erb | 34 +- app/views/english_offers/show.html.erb | 4 +- app/views/invoices/index.html.erb | 5 - app/views/invoices/show.html.erb | 2 +- app/views/layouts/application.html.erb | 5 +- app/views/notifications/index.html.erb | 71 +- app/views/offers/_offer.html.erb | 3 +- app/views/offers/delete.html.erb | 18 + app/views/offers/edit.html.erb | 2 +- app/views/offers/index.html.erb | 4 - app/views/offers/new.html.erb | 2 +- app/views/offers/show.html.erb | 4 +- app/views/results/show.html.erb | 2 +- .../{_form.html.erb => _form2.html.erb} | 0 app/views/wishlist_items/_editable.html.erb | 14 +- .../wishlist_items/_wishlist_items.html.erb | 42 + app/views/wishlist_items/index.html.erb | 50 +- config/locales/en.yml | 2 +- config/locales/et.yml | 2 +- config/routes.rb | 4 +- package.json | 4 +- 68 files changed, 6909 insertions(+), 6168 deletions(-) create mode 100644 app/assets/stylesheets/components/_address.scss create mode 100644 app/assets/stylesheets/components/_table-whishlist.scss create mode 100644 app/assets/stylesheets/components/_wishlist.scss delete mode 100644 app/channels/notification_channel.rb create mode 100644 app/javascript/controllers/hamburger_controller.js create mode 100644 app/views/billing_profiles/_new_form.html.erb create mode 100644 app/views/offers/delete.html.erb rename app/views/users/deprecated/{_form.html.erb => _form2.html.erb} (100%) create mode 100644 app/views/wishlist_items/_wishlist_items.html.erb diff --git a/app/assets/builds/application.css b/app/assets/builds/application.css index 633af5507..265209dc5 100644 --- a/app/assets/builds/application.css +++ b/app/assets/builds/application.css @@ -1914,6 +1914,12 @@ input:not([type=checkbox]):not([type=radio]).is-invalid + span, select.is-invali } } +@media all and (min-width: 992px) { + .o-grid--two-col-laptop { + grid-template-columns: repeat(2, 1fr); + } +} + @media all and (min-width: 1120px) { .o-grid--two-col-desktop { grid-template-columns: repeat(2, 1fr); @@ -1930,6 +1936,20 @@ input:not([type=checkbox]):not([type=radio]).is-invalid + span, select.is-invali row-gap: 3rem; } +.o-grid--wishlist { + row-gap: 1.5rem; +} +@media all and (min-width: 768px) { + .o-grid--wishlist { + row-gap: 2.5rem; + } +} +@media all and (min-width: 992px) { + .o-grid--wishlist { + row-gap: 0; + } +} + .o-io-icon { display: inline-block; vertical-align: middle; @@ -3633,6 +3653,25 @@ input:not([type=checkbox]):not([type=radio]).is-invalid + span, select.is-invali padding: 0; } +.c-cta--wishlist { + background: #fff; + margin-bottom: 1.5rem; + padding-bottom: 60px; + box-shadow: 0 0 48px rgba(0, 0, 0, 0.12); +} +@media all and (min-width: 768px) { + .c-cta--wishlist { + margin-bottom: 2.5rem; + padding-bottom: 0px; + box-shadow: unset; + } +} +@media all and (min-width: 992px) { + .c-cta--wishlist { + margin-bottom: 3.75rem; + } +} + .c-btn--orange { font-weight: 500; font-size: 1rem; @@ -5482,6 +5521,10 @@ table .c-btn--icon { margin: 0; } +.c-account--mainpage .c-account_editicons > svg:first-child { + display: none; +} + .c-account_editicons { gap: 8px; position: absolute; @@ -5501,35 +5544,17 @@ table .c-btn--icon { opacity: 1; transition: opacity 0.3s; } -.c-account_editicons > svg:not(:first-child) { +.c-account_editicons > svg:nth-last-child(-n+2) { display: none; } .c-account_editicons > svg:hover { opacity: 0.7; } -.c-account_editicons.is-editable .c-account_editicons--reset { +.c-account_editicons.is-editable > svg:nth-last-child(-n+2) { display: inline-flex; } -.c-account_editicons.is-editable .c-account_editicons--reset svg { - display: block; -} -.c-account_editicons.is-editable > svg:not(:first-child) { - display: inline-flex; -} -.c-account_editicons.is-editable > svg:first-child { - display: none; -} - -.c-account_editicons--reset { +.c-account_editicons.is-editable > svg:nth-child(-n+2) { display: none; - padding: 0; - border: 0; - background-color: transparent; - opacity: 1; - transition: opacity 0.3s; -} -.c-account_editicons--reset:hover { - opacity: 0.7; } .c-account__input-wrapper { @@ -5545,17 +5570,19 @@ table .c-btn--icon { } } .c-account__input-wrapper .c-account__input { - width: 50%; + width: 100%; flex-shrink: 0; } +@media all and (min-width: 374px) { + .c-account__input-wrapper .c-account__input { + width: 50%; + } +} @media all and (min-width: 768px) { .c-account__input-wrapper .c-account__input { width: 131px; } } -.c-account__input-wrapper .c-account__input:last-child { - margin-bottom: 0; -} @media all and (min-width: 768px) { .c-account__input-wrapper .c-account__input:last-child { width: 165px; @@ -5578,11 +5605,11 @@ table .c-btn--icon { padding: 0; } -.c-account__input--editable input { +.c-account__input--editable input, .c-account__input--editable select { border-color: transparent; transition: border 0.5s; } -.c-account__input--editable.is-editable input { +.c-account__input--editable.is-editable input, .c-account__input--editable.is-editable select { border: 1px solid #e2e2e2; } @@ -5600,7 +5627,7 @@ table .c-btn--icon { line-height: 1.5rem; } -a.c-acount__link { +.c-acount__link { color: #0085ca; font-size: 0.875rem; font-weight: 500; @@ -5613,7 +5640,7 @@ a.c-acount__link { .c-acount__buttons { gap: 5px; } -@media all and (min-width: 320px) { +@media all and (min-width: 374px) { .c-acount__buttons { gap: 10px; } @@ -5627,7 +5654,7 @@ a.c-acount__link { .c-acount__button { font-size: 0.6875rem; } -@media all and (min-width: 320px) { +@media all and (min-width: 374px) { .c-acount__button { font-size: 0.875rem; } @@ -5639,6 +5666,265 @@ a.c-acount__link { gap: 10px; } +.c-wishlist__table tr th { + white-space: nowrap; +} +.c-wishlist__table tbody { + margin-top: 1.5rem; +} +@media all and (min-width: 992px) { + .c-wishlist__table tbody { + margin-top: 1.875rem; + } +} +@media all and (min-width: 992px) { + .c-wishlist__table tbody { + margin-top: 0; + } +} +.c-wishlist__table tbody tr td:nth-child(1) { + order: 2; + margin-left: auto; + font-weight: 800; +} +@media all and (min-width: 992px) { + .c-wishlist__table tbody tr td:nth-child(1) { + order: 1; + margin-left: 0; + font-weight: 500; + } +} +.c-wishlist__table tbody tr td:nth-child(2) { + font-weight: 800; + order: 1; + margin-left: 0; + max-width: 90%; + margin-bottom: 0.5rem; +} +@media all and (min-width: 992px) { + .c-wishlist__table tbody tr td:nth-child(2) { + order: 2; + width: 100%; + margin-bottom: 0; + } +} +.c-wishlist__table tbody tr td:nth-child(3) { + order: 3; + margin-bottom: 0.875rem; +} +@media all and (min-width: 992px) { + .c-wishlist__table tbody tr td:nth-child(3) { + margin-bottom: 0; + } +} +.c-wishlist__table tbody tr td:nth-child(4) { + order: 4; +} + +.c-table__filters__search--whishlist { + margin: 0 -1rem; +} +@media all and (min-width: 768px) { + .c-table__filters__search--whishlist { + margin: auto; + } +} +.c-table__filters__search--whishlist .c-table__filters__search { + text-align: left; +} +.c-table__filters__search--whishlist input { + width: 11.25rem; + margin-right: 0.3125rem; + font-size: 0.75rem; +} +@media all and (min-width: 374px) { + .c-table__filters__search--whishlist input { + width: 15.9375rem; + margin-right: 1rem; + font-size: 0.875rem; + } +} +@media all and (min-width: 992px) { + .c-table__filters__search--whishlist input { + width: 550px; + } +} + +.c-whishlist__notice { + font-size: 0.875rem; + font-weight: 500; + line-height: 1.5rem; + display: inline-block; + padding-top: 30px; +} +@media all and (min-width: 768px) { + .c-whishlist__notice { + padding-top: 40px; + } +} +@media all and (min-width: 992px) { + .c-whishlist__notice { + padding-top: 60px; + } +} + +.c-wishlist__btn { + font-size: 0.875rem; +} + +.c-account--adresses input { + max-width: 550px; +} +.c-account--adresses .c-account__input-title { + gap: 40px; +} +.c-account--adresses .c-account__input-title input { + border-radius: 0; +} +.c-account--adresses .c-account__input-title.is-editable input { + border-color: transparent; + border-bottom-color: #E2E2E2; +} +.c-account--adresses .c-account__input-wrapper { + max-width: 100%; + flex-wrap: wrap; + gap: 8px; +} +@media all and (min-width: 768px) { + .c-account--adresses .c-account__input-wrapper { + gap: 16px; + } +} +.c-account--adresses .c-account__input-wrapper .c-account__input input { + width: 100%; +} +.c-account--adresses .c-account__input-wrapper .c-account__input select { + cursor: pointer; + min-width: 62px; + width: fit-content; + background-position: right 0.6rem center; +} +.c-account--adresses .c-account__input-wrapper .c-account__input:nth-child(1) { + width: 100%; +} +.c-account--adresses .c-account__input-wrapper .c-account__input:nth-child(2) { + width: 88px; +} +.c-account--adresses .c-account__input-wrapper .c-account__input:nth-child(3) { + width: 88px; +} +.c-account--adresses .c-account__input-wrapper .c-account__input:nth-child(4) { + width: fit-content; +} +@media all and (min-width: 768px) { + .c-account--adresses .c-account__input-wrapper .c-account__input:nth-child(1) { + width: 200px; + } + .c-account--adresses .c-account__input-wrapper .c-account__input:nth-child(2) { + width: 130px; + } + .c-account--adresses .c-account__input-wrapper .c-account__input:nth-child(3) { + width: 108px; + } +} +@media all and (min-width: 1120px) { + .c-account--adresses .c-account__input-wrapper .c-account__input:nth-child(1) { + width: 100%; + } + .c-account--adresses .c-account__input-wrapper .c-account__input:nth-child(2) { + width: 88px; + } + .c-account--adresses .c-account__input-wrapper .c-account__input:nth-child(3) { + width: 88px; + } +} +@media all and (min-width: 1480px) { + .c-account--adresses .c-account__input-wrapper .c-account__input:nth-child(1) { + width: 200px; + } + .c-account--adresses .c-account__input-wrapper .c-account__input:nth-child(2) { + width: 130px; + } + .c-account--adresses .c-account__input-wrapper .c-account__input:nth-child(3) { + width: 108px; + } +} + +.pagy-nav .page.prev, +.pagy-nav .page.prev a, +.pagy-nav .page.next, +.pagy-nav .page.next a { + width: 2rem; + height: 2rem; + border-radius: 1rem !important; + border: 1px solid #E2E2E2 !important; + display: flex !important; + justify-content: center; + align-items: center; + padding: 0 !important; + font-weight: 500; + font-size: 0.875rem; + line-height: 1.5rem; + border: none !important; + padding: 0.25rem 0.25rem !important; + width: 5rem; +} + +.pagy-nav .page.active { + width: 2rem; + height: 2rem; + border-radius: 1rem !important; + border: 1px solid #E2E2E2 !important; + display: flex !important; + justify-content: center; + align-items: center; + padding: 0 !important; + font-weight: 500; + font-size: 0.875rem; + line-height: 1.5rem; + background-color: #48A23F !important; + border-color: #48A23F !important; + color: #FFFFFF !important; +} + +.pagy-nav .page.gap { + margin-left: 0.25rem; + margin-right: 0.25rem; +} + +.pagy-nav .page a { + text-decoration: none; + color: black !important; + width: 2rem; + height: 2rem; + border-radius: 1rem !important; + border: 1px solid #E2E2E2 !important; + display: flex !important; + justify-content: center; + align-items: center; + padding: 0 !important; + font-weight: 500; + font-size: 0.875rem; + line-height: 1.5rem; +} + +.pagy-nav .page a:hover { + color: #212224 !important; + background: #E2E2E2 !important; +} + +.pagy-nav { + display: flex; + justify-content: center; + width: 100%; + margin-top: 3rem; + gap: 1.5rem; +} +.pagy-nav span { + display: flex; + gap: 0.5rem; +} + .u-clear-both { clear: both; } @@ -5857,6 +6143,10 @@ a.c-acount__link { margin-top: 3rem; } +.u-mt-60 { + margin-top: 3.75rem; +} + .u-mt-8 { margin-top: 0.5rem; } @@ -5867,6 +6157,10 @@ a.c-acount__link { } } +.u-mb-60 { + margin-bottom: 3.75rem; +} + .u-mb-48 { margin-bottom: 3rem; } diff --git a/app/assets/builds/application.js b/app/assets/builds/application.js index 77d78be40..4b41a674c 100644 --- a/app/assets/builds/application.js +++ b/app/assets/builds/application.js @@ -655,10 +655,10 @@ }); // node_modules/@hotwired/turbo-rails/node_modules/@rails/actioncable/src/subscription.js - var extend2, Subscription; + var extend, Subscription; var init_subscription = __esm({ "node_modules/@hotwired/turbo-rails/node_modules/@rails/actioncable/src/subscription.js"() { - extend2 = function(object, properties) { + extend = function(object, properties) { if (properties != null) { for (let key in properties) { const value = properties[key]; @@ -671,7 +671,7 @@ constructor(consumer2, params = {}, mixin) { this.consumer = consumer2; this.identifier = JSON.stringify(params); - extend2(this, mixin); + extend(this, mixin); } perform(action, data = {}) { data.action = action; @@ -901,7002 +901,7013 @@ } }); - // node_modules/@hotwired/stimulus/dist/stimulus.js - var EventListener = class { - constructor(eventTarget, eventName, eventOptions) { - this.eventTarget = eventTarget; - this.eventName = eventName; - this.eventOptions = eventOptions; - this.unorderedBindings = /* @__PURE__ */ new Set(); + // node_modules/@hotwired/turbo/dist/turbo.es2017-esm.js + (function() { + if (window.Reflect === void 0 || window.customElements === void 0 || window.customElements.polyfillWrapFlushCallback) { + return; } - connect() { - this.eventTarget.addEventListener(this.eventName, this, this.eventOptions); + const BuiltInHTMLElement = HTMLElement; + const wrapperForTheName = { + HTMLElement: function HTMLElement2() { + return Reflect.construct(BuiltInHTMLElement, [], this.constructor); + } + }; + window.HTMLElement = wrapperForTheName["HTMLElement"]; + HTMLElement.prototype = BuiltInHTMLElement.prototype; + HTMLElement.prototype.constructor = HTMLElement; + Object.setPrototypeOf(HTMLElement, BuiltInHTMLElement); + })(); + (function(prototype) { + if (typeof prototype.requestSubmit == "function") + return; + prototype.requestSubmit = function(submitter) { + if (submitter) { + validateSubmitter(submitter, this); + submitter.click(); + } else { + submitter = document.createElement("input"); + submitter.type = "submit"; + submitter.hidden = true; + this.appendChild(submitter); + submitter.click(); + this.removeChild(submitter); + } + }; + function validateSubmitter(submitter, form) { + submitter instanceof HTMLElement || raise(TypeError, "parameter 1 is not of type 'HTMLElement'"); + submitter.type == "submit" || raise(TypeError, "The specified element is not a submit button"); + submitter.form == form || raise(DOMException, "The specified element is not owned by this form element", "NotFoundError"); } - disconnect() { - this.eventTarget.removeEventListener(this.eventName, this, this.eventOptions); + function raise(errorConstructor, message, name) { + throw new errorConstructor("Failed to execute 'requestSubmit' on 'HTMLFormElement': " + message + ".", name); } - bindingConnected(binding) { - this.unorderedBindings.add(binding); + })(HTMLFormElement.prototype); + var submittersByForm = /* @__PURE__ */ new WeakMap(); + function findSubmitterFromClickTarget(target) { + const element = target instanceof Element ? target : target instanceof Node ? target.parentElement : null; + const candidate = element ? element.closest("input, button") : null; + return (candidate === null || candidate === void 0 ? void 0 : candidate.type) == "submit" ? candidate : null; + } + function clickCaptured(event) { + const submitter = findSubmitterFromClickTarget(event.target); + if (submitter && submitter.form) { + submittersByForm.set(submitter.form, submitter); } - bindingDisconnected(binding) { - this.unorderedBindings.delete(binding); + } + (function() { + if ("submitter" in Event.prototype) + return; + let prototype = window.Event.prototype; + if ("SubmitEvent" in window && /Apple Computer/.test(navigator.vendor)) { + prototype = window.SubmitEvent.prototype; + } else if ("SubmitEvent" in window) { + return; } - handleEvent(event) { - const extendedEvent = extendEvent(event); - for (const binding of this.bindings) { - if (extendedEvent.immediatePropagationStopped) { - break; - } else { - binding.handleEvent(extendedEvent); + addEventListener("click", clickCaptured, true); + Object.defineProperty(prototype, "submitter", { + get() { + if (this.type == "submit" && this.target instanceof HTMLFormElement) { + return submittersByForm.get(this.target); } } + }); + })(); + var FrameLoadingStyle; + (function(FrameLoadingStyle2) { + FrameLoadingStyle2["eager"] = "eager"; + FrameLoadingStyle2["lazy"] = "lazy"; + })(FrameLoadingStyle || (FrameLoadingStyle = {})); + var FrameElement = class extends HTMLElement { + static get observedAttributes() { + return ["disabled", "complete", "loading", "src"]; } - hasBindings() { - return this.unorderedBindings.size > 0; - } - get bindings() { - return Array.from(this.unorderedBindings).sort((left, right) => { - const leftIndex = left.index, rightIndex = right.index; - return leftIndex < rightIndex ? -1 : leftIndex > rightIndex ? 1 : 0; - }); + constructor() { + super(); + this.loaded = Promise.resolve(); + this.delegate = new FrameElement.delegateConstructor(this); } - }; - function extendEvent(event) { - if ("immediatePropagationStopped" in event) { - return event; - } else { - const { stopImmediatePropagation } = event; - return Object.assign(event, { - immediatePropagationStopped: false, - stopImmediatePropagation() { - this.immediatePropagationStopped = true; - stopImmediatePropagation.call(this); - } - }); + connectedCallback() { + this.delegate.connect(); } - } - var Dispatcher = class { - constructor(application2) { - this.application = application2; - this.eventListenerMaps = /* @__PURE__ */ new Map(); - this.started = false; + disconnectedCallback() { + this.delegate.disconnect(); } - start() { - if (!this.started) { - this.started = true; - this.eventListeners.forEach((eventListener) => eventListener.connect()); - } + reload() { + return this.delegate.sourceURLReloaded(); } - stop() { - if (this.started) { - this.started = false; - this.eventListeners.forEach((eventListener) => eventListener.disconnect()); + attributeChangedCallback(name) { + if (name == "loading") { + this.delegate.loadingStyleChanged(); + } else if (name == "complete") { + this.delegate.completeChanged(); + } else if (name == "src") { + this.delegate.sourceURLChanged(); + } else { + this.delegate.disabledChanged(); } } - get eventListeners() { - return Array.from(this.eventListenerMaps.values()).reduce((listeners, map) => listeners.concat(Array.from(map.values())), []); - } - bindingConnected(binding) { - this.fetchEventListenerForBinding(binding).bindingConnected(binding); - } - bindingDisconnected(binding, clearEventListeners = false) { - this.fetchEventListenerForBinding(binding).bindingDisconnected(binding); - if (clearEventListeners) - this.clearEventListenersForBinding(binding); - } - handleError(error2, message, detail = {}) { - this.application.handleError(error2, `Error ${message}`, detail); + get src() { + return this.getAttribute("src"); } - clearEventListenersForBinding(binding) { - const eventListener = this.fetchEventListenerForBinding(binding); - if (!eventListener.hasBindings()) { - eventListener.disconnect(); - this.removeMappedEventListenerFor(binding); + set src(value) { + if (value) { + this.setAttribute("src", value); + } else { + this.removeAttribute("src"); } } - removeMappedEventListenerFor(binding) { - const { eventTarget, eventName, eventOptions } = binding; - const eventListenerMap = this.fetchEventListenerMapForEventTarget(eventTarget); - const cacheKey = this.cacheKey(eventName, eventOptions); - eventListenerMap.delete(cacheKey); - if (eventListenerMap.size == 0) - this.eventListenerMaps.delete(eventTarget); - } - fetchEventListenerForBinding(binding) { - const { eventTarget, eventName, eventOptions } = binding; - return this.fetchEventListener(eventTarget, eventName, eventOptions); + get loading() { + return frameLoadingStyleFromString(this.getAttribute("loading") || ""); } - fetchEventListener(eventTarget, eventName, eventOptions) { - const eventListenerMap = this.fetchEventListenerMapForEventTarget(eventTarget); - const cacheKey = this.cacheKey(eventName, eventOptions); - let eventListener = eventListenerMap.get(cacheKey); - if (!eventListener) { - eventListener = this.createEventListener(eventTarget, eventName, eventOptions); - eventListenerMap.set(cacheKey, eventListener); + set loading(value) { + if (value) { + this.setAttribute("loading", value); + } else { + this.removeAttribute("loading"); } - return eventListener; } - createEventListener(eventTarget, eventName, eventOptions) { - const eventListener = new EventListener(eventTarget, eventName, eventOptions); - if (this.started) { - eventListener.connect(); - } - return eventListener; + get disabled() { + return this.hasAttribute("disabled"); } - fetchEventListenerMapForEventTarget(eventTarget) { - let eventListenerMap = this.eventListenerMaps.get(eventTarget); - if (!eventListenerMap) { - eventListenerMap = /* @__PURE__ */ new Map(); - this.eventListenerMaps.set(eventTarget, eventListenerMap); + set disabled(value) { + if (value) { + this.setAttribute("disabled", ""); + } else { + this.removeAttribute("disabled"); } - return eventListenerMap; } - cacheKey(eventName, eventOptions) { - const parts = [eventName]; - Object.keys(eventOptions).sort().forEach((key) => { - parts.push(`${eventOptions[key] ? "" : "!"}${key}`); - }); - return parts.join(":"); + get autoscroll() { + return this.hasAttribute("autoscroll"); } - }; - var defaultActionDescriptorFilters = { - stop({ event, value }) { - if (value) - event.stopPropagation(); - return true; - }, - prevent({ event, value }) { - if (value) - event.preventDefault(); - return true; - }, - self({ event, value, element }) { + set autoscroll(value) { if (value) { - return element === event.target; + this.setAttribute("autoscroll", ""); } else { - return true; + this.removeAttribute("autoscroll"); } } + get complete() { + return !this.delegate.isLoading; + } + get isActive() { + return this.ownerDocument === document && !this.isPreview; + } + get isPreview() { + var _a, _b; + return (_b = (_a = this.ownerDocument) === null || _a === void 0 ? void 0 : _a.documentElement) === null || _b === void 0 ? void 0 : _b.hasAttribute("data-turbo-preview"); + } }; - var descriptorPattern = /^(?:(.+?)(?:\.(.+?))?(?:@(window|document))?->)?(.+?)(?:#([^:]+?))(?::(.+))?$/; - function parseActionDescriptorString(descriptorString) { - const source = descriptorString.trim(); - const matches = source.match(descriptorPattern) || []; - let eventName = matches[1]; - let keyFilter = matches[2]; - if (keyFilter && !["keydown", "keyup", "keypress"].includes(eventName)) { - eventName += `.${keyFilter}`; - keyFilter = ""; + function frameLoadingStyleFromString(style) { + switch (style.toLowerCase()) { + case "lazy": + return FrameLoadingStyle.lazy; + default: + return FrameLoadingStyle.eager; } - return { - eventTarget: parseEventTarget(matches[3]), - eventName, - eventOptions: matches[6] ? parseEventOptions(matches[6]) : {}, - identifier: matches[4], - methodName: matches[5], - keyFilter - }; } - function parseEventTarget(eventTargetName) { - if (eventTargetName == "window") { - return window; - } else if (eventTargetName == "document") { - return document; + function expandURL(locatable) { + return new URL(locatable.toString(), document.baseURI); + } + function getAnchor(url) { + let anchorMatch; + if (url.hash) { + return url.hash.slice(1); + } else if (anchorMatch = url.href.match(/#(.*)$/)) { + return anchorMatch[1]; } } - function parseEventOptions(eventOptions) { - return eventOptions.split(":").reduce((options, token) => Object.assign(options, { [token.replace(/^!/, "")]: !/^!/.test(token) }), {}); + function getAction(form, submitter) { + const action = (submitter === null || submitter === void 0 ? void 0 : submitter.getAttribute("formaction")) || form.getAttribute("action") || form.action; + return expandURL(action); } - function stringifyEventTarget(eventTarget) { - if (eventTarget == window) { - return "window"; - } else if (eventTarget == document) { - return "document"; - } + function getExtension(url) { + return (getLastPathComponent(url).match(/\.[^.]*$/) || [])[0] || ""; } - function camelize(value) { - return value.replace(/(?:[_-])([a-z0-9])/g, (_, char) => char.toUpperCase()); + function isHTML(url) { + return !!getExtension(url).match(/^(?:|\.(?:htm|html|xhtml|php))$/); } - function namespaceCamelize(value) { - return camelize(value.replace(/--/g, "-").replace(/__/g, "_")); + function isPrefixedBy(baseURL, url) { + const prefix = getPrefix(url); + return baseURL.href === expandURL(prefix).href || baseURL.href.startsWith(prefix); } - function capitalize(value) { - return value.charAt(0).toUpperCase() + value.slice(1); + function locationIsVisitable(location2, rootLocation) { + return isPrefixedBy(location2, rootLocation) && isHTML(location2); } - function dasherize(value) { - return value.replace(/([A-Z])/g, (_, char) => `-${char.toLowerCase()}`); + function getRequestURL(url) { + const anchor = getAnchor(url); + return anchor != null ? url.href.slice(0, -(anchor.length + 1)) : url.href; } - function tokenize(value) { - return value.match(/[^\s]+/g) || []; + function toCacheKey(url) { + return getRequestURL(url); } - var Action = class { - constructor(element, index, descriptor, schema) { - this.element = element; - this.index = index; - this.eventTarget = descriptor.eventTarget || element; - this.eventName = descriptor.eventName || getDefaultEventNameForElement(element) || error("missing event name"); - this.eventOptions = descriptor.eventOptions || {}; - this.identifier = descriptor.identifier || error("missing identifier"); - this.methodName = descriptor.methodName || error("missing method name"); - this.keyFilter = descriptor.keyFilter || ""; - this.schema = schema; - } - static forToken(token, schema) { - return new this(token.element, token.index, parseActionDescriptorString(token.content), schema); - } - toString() { - const eventFilter = this.keyFilter ? `.${this.keyFilter}` : ""; - const eventTarget = this.eventTargetName ? `@${this.eventTargetName}` : ""; - return `${this.eventName}${eventFilter}${eventTarget}->${this.identifier}#${this.methodName}`; - } - isFilterTarget(event) { - if (!this.keyFilter) { - return false; - } - const filteres = this.keyFilter.split("+"); - const modifiers = ["meta", "ctrl", "alt", "shift"]; - const [meta, ctrl, alt, shift] = modifiers.map((modifier) => filteres.includes(modifier)); - if (event.metaKey !== meta || event.ctrlKey !== ctrl || event.altKey !== alt || event.shiftKey !== shift) { - return true; - } - const standardFilter = filteres.filter((key) => !modifiers.includes(key))[0]; - if (!standardFilter) { - return false; - } - if (!Object.prototype.hasOwnProperty.call(this.keyMappings, standardFilter)) { - error(`contains unknown key filter: ${this.keyFilter}`); - } - return this.keyMappings[standardFilter].toLowerCase() !== event.key.toLowerCase(); - } - get params() { - const params = {}; - const pattern = new RegExp(`^data-${this.identifier}-(.+)-param$`, "i"); - for (const { name, value } of Array.from(this.element.attributes)) { - const match = name.match(pattern); - const key = match && match[1]; - if (key) { - params[camelize(key)] = typecast(value); - } - } - return params; - } - get eventTargetName() { - return stringifyEventTarget(this.eventTarget); - } - get keyMappings() { - return this.schema.keyMappings; - } - }; - var defaultEventNames = { - a: () => "click", - button: () => "click", - form: () => "submit", - details: () => "toggle", - input: (e) => e.getAttribute("type") == "submit" ? "click" : "input", - select: () => "change", - textarea: () => "input" - }; - function getDefaultEventNameForElement(element) { - const tagName = element.tagName.toLowerCase(); - if (tagName in defaultEventNames) { - return defaultEventNames[tagName](element); - } + function urlsAreEqual(left, right) { + return expandURL(left).href == expandURL(right).href; } - function error(message) { - throw new Error(message); + function getPathComponents(url) { + return url.pathname.split("/").slice(1); } - function typecast(value) { - try { - return JSON.parse(value); - } catch (o_O) { - return value; - } + function getLastPathComponent(url) { + return getPathComponents(url).slice(-1)[0]; } - var Binding = class { - constructor(context, action) { - this.context = context; - this.action = action; + function getPrefix(url) { + return addTrailingSlash(url.origin + url.pathname); + } + function addTrailingSlash(value) { + return value.endsWith("/") ? value : value + "/"; + } + var FetchResponse = class { + constructor(response) { + this.response = response; } - get index() { - return this.action.index; + get succeeded() { + return this.response.ok; } - get eventTarget() { - return this.action.eventTarget; + get failed() { + return !this.succeeded; } - get eventOptions() { - return this.action.eventOptions; + get clientError() { + return this.statusCode >= 400 && this.statusCode <= 499; } - get identifier() { - return this.context.identifier; + get serverError() { + return this.statusCode >= 500 && this.statusCode <= 599; } - handleEvent(event) { - if (this.willBeInvokedByEvent(event) && this.applyEventModifiers(event)) { - this.invokeWithEvent(event); - } + get redirected() { + return this.response.redirected; } - get eventName() { - return this.action.eventName; + get location() { + return expandURL(this.response.url); } - get method() { - const method = this.controller[this.methodName]; - if (typeof method == "function") { - return method; - } - throw new Error(`Action "${this.action}" references undefined method "${this.methodName}"`); + get isHTML() { + return this.contentType && this.contentType.match(/^(?:text\/([^\s;,]+\b)?html|application\/xhtml\+xml)\b/); } - applyEventModifiers(event) { - const { element } = this.action; - const { actionDescriptorFilters } = this.context.application; - let passes = true; - for (const [name, value] of Object.entries(this.eventOptions)) { - if (name in actionDescriptorFilters) { - const filter = actionDescriptorFilters[name]; - passes = passes && filter({ name, value, event, element }); - } else { - continue; - } - } - return passes; + get statusCode() { + return this.response.status; } - invokeWithEvent(event) { - const { target, currentTarget } = event; - try { - const { params } = this.action; - const actionEvent = Object.assign(event, { params }); - this.method.call(this.controller, actionEvent); - this.context.logDebugActivity(this.methodName, { event, target, currentTarget, action: this.methodName }); - } catch (error2) { - const { identifier, controller, element, index } = this; - const detail = { identifier, controller, element, index, event }; - this.context.handleError(error2, `invoking action "${this.action}"`, detail); - } + get contentType() { + return this.header("Content-Type"); } - willBeInvokedByEvent(event) { - const eventTarget = event.target; - if (event instanceof KeyboardEvent && this.action.isFilterTarget(event)) { - return false; - } - if (this.element === eventTarget) { - return true; - } else if (eventTarget instanceof Element && this.element.contains(eventTarget)) { - return this.scope.containsElement(eventTarget); + get responseText() { + return this.response.clone().text(); + } + get responseHTML() { + if (this.isHTML) { + return this.response.clone().text(); } else { - return this.scope.containsElement(this.action.element); + return Promise.resolve(void 0); } } - get controller() { - return this.context.controller; - } - get methodName() { - return this.action.methodName; - } - get element() { - return this.scope.element; - } - get scope() { - return this.context.scope; + header(name) { + return this.response.headers.get(name); } }; - var ElementObserver = class { - constructor(element, delegate) { - this.mutationObserverInit = { attributes: true, childList: true, subtree: true }; - this.element = element; - this.started = false; - this.delegate = delegate; - this.elements = /* @__PURE__ */ new Set(); - this.mutationObserver = new MutationObserver((mutations) => this.processMutations(mutations)); - } - start() { - if (!this.started) { - this.started = true; - this.mutationObserver.observe(this.element, this.mutationObserverInit); - this.refresh(); - } - } - pause(callback) { - if (this.started) { - this.mutationObserver.disconnect(); - this.started = false; - } - callback(); - if (!this.started) { - this.mutationObserver.observe(this.element, this.mutationObserverInit); - this.started = true; - } - } - stop() { - if (this.started) { - this.mutationObserver.takeRecords(); - this.mutationObserver.disconnect(); - this.started = false; + function activateScriptElement(element) { + if (element.getAttribute("data-turbo-eval") == "false") { + return element; + } else { + const createdScriptElement = document.createElement("script"); + const cspNonce = getMetaContent("csp-nonce"); + if (cspNonce) { + createdScriptElement.nonce = cspNonce; } + createdScriptElement.textContent = element.textContent; + createdScriptElement.async = false; + copyElementAttributes(createdScriptElement, element); + return createdScriptElement; } - refresh() { - if (this.started) { - const matches = new Set(this.matchElementsInTree()); - for (const element of Array.from(this.elements)) { - if (!matches.has(element)) { - this.removeElement(element); - } - } - for (const element of Array.from(matches)) { - this.addElement(element); - } - } + } + function copyElementAttributes(destinationElement, sourceElement) { + for (const { name, value } of sourceElement.attributes) { + destinationElement.setAttribute(name, value); } - processMutations(mutations) { - if (this.started) { - for (const mutation of mutations) { - this.processMutation(mutation); - } - } + } + function createDocumentFragment(html) { + const template = document.createElement("template"); + template.innerHTML = html; + return template.content; + } + function dispatch(eventName, { target, cancelable, detail } = {}) { + const event = new CustomEvent(eventName, { + cancelable, + bubbles: true, + composed: true, + detail + }); + if (target && target.isConnected) { + target.dispatchEvent(event); + } else { + document.documentElement.dispatchEvent(event); } - processMutation(mutation) { - if (mutation.type == "attributes") { - this.processAttributeChange(mutation.target, mutation.attributeName); - } else if (mutation.type == "childList") { - this.processRemovedNodes(mutation.removedNodes); - this.processAddedNodes(mutation.addedNodes); + return event; + } + function nextAnimationFrame() { + return new Promise((resolve) => requestAnimationFrame(() => resolve())); + } + function nextEventLoopTick() { + return new Promise((resolve) => setTimeout(() => resolve(), 0)); + } + function nextMicrotask() { + return Promise.resolve(); + } + function parseHTMLDocument(html = "") { + return new DOMParser().parseFromString(html, "text/html"); + } + function unindent(strings, ...values) { + const lines = interpolate(strings, values).replace(/^\n/, "").split("\n"); + const match = lines[0].match(/^\s+/); + const indent = match ? match[0].length : 0; + return lines.map((line) => line.slice(indent)).join("\n"); + } + function interpolate(strings, values) { + return strings.reduce((result, string, i) => { + const value = values[i] == void 0 ? "" : values[i]; + return result + string + value; + }, ""); + } + function uuid() { + return Array.from({ length: 36 }).map((_, i) => { + if (i == 8 || i == 13 || i == 18 || i == 23) { + return "-"; + } else if (i == 14) { + return "4"; + } else if (i == 19) { + return (Math.floor(Math.random() * 4) + 8).toString(16); + } else { + return Math.floor(Math.random() * 15).toString(16); } + }).join(""); + } + function getAttribute(attributeName, ...elements) { + for (const value of elements.map((element) => element === null || element === void 0 ? void 0 : element.getAttribute(attributeName))) { + if (typeof value == "string") + return value; } - processAttributeChange(node, attributeName) { - const element = node; - if (this.elements.has(element)) { - if (this.delegate.elementAttributeChanged && this.matchElement(element)) { - this.delegate.elementAttributeChanged(element, attributeName); - } else { - this.removeElement(element); - } - } else if (this.matchElement(element)) { - this.addElement(element); + return null; + } + function hasAttribute(attributeName, ...elements) { + return elements.some((element) => element && element.hasAttribute(attributeName)); + } + function markAsBusy(...elements) { + for (const element of elements) { + if (element.localName == "turbo-frame") { + element.setAttribute("busy", ""); } + element.setAttribute("aria-busy", "true"); } - processRemovedNodes(nodes) { - for (const node of Array.from(nodes)) { - const element = this.elementFromNode(node); - if (element) { - this.processTree(element, this.removeElement); - } + } + function clearBusyState(...elements) { + for (const element of elements) { + if (element.localName == "turbo-frame") { + element.removeAttribute("busy"); } + element.removeAttribute("aria-busy"); } - processAddedNodes(nodes) { - for (const node of Array.from(nodes)) { - const element = this.elementFromNode(node); - if (element && this.elementIsActive(element)) { - this.processTree(element, this.addElement); - } - } + } + function waitForLoad(element, timeoutInMilliseconds = 2e3) { + return new Promise((resolve) => { + const onComplete = () => { + element.removeEventListener("error", onComplete); + element.removeEventListener("load", onComplete); + resolve(); + }; + element.addEventListener("load", onComplete, { once: true }); + element.addEventListener("error", onComplete, { once: true }); + setTimeout(resolve, timeoutInMilliseconds); + }); + } + function getHistoryMethodForAction(action) { + switch (action) { + case "replace": + return history.replaceState; + case "advance": + case "restore": + return history.pushState; } - matchElement(element) { - return this.delegate.matchElement(element); + } + function isAction(action) { + return action == "advance" || action == "replace" || action == "restore"; + } + function getVisitAction(...elements) { + const action = getAttribute("data-turbo-action", ...elements); + return isAction(action) ? action : null; + } + function getMetaElement(name) { + return document.querySelector(`meta[name="${name}"]`); + } + function getMetaContent(name) { + const element = getMetaElement(name); + return element && element.content; + } + function setMetaContent(name, content) { + let element = getMetaElement(name); + if (!element) { + element = document.createElement("meta"); + element.setAttribute("name", name); + document.head.appendChild(element); } - matchElementsInTree(tree = this.element) { - return this.delegate.matchElementsInTree(tree); + element.setAttribute("content", content); + return element; + } + function findClosestRecursively(element, selector) { + var _a; + if (element instanceof Element) { + return element.closest(selector) || findClosestRecursively(element.assignedSlot || ((_a = element.getRootNode()) === null || _a === void 0 ? void 0 : _a.host), selector); } - processTree(tree, processor) { - for (const element of this.matchElementsInTree(tree)) { - processor.call(this, element); - } + } + var FetchMethod; + (function(FetchMethod2) { + FetchMethod2[FetchMethod2["get"] = 0] = "get"; + FetchMethod2[FetchMethod2["post"] = 1] = "post"; + FetchMethod2[FetchMethod2["put"] = 2] = "put"; + FetchMethod2[FetchMethod2["patch"] = 3] = "patch"; + FetchMethod2[FetchMethod2["delete"] = 4] = "delete"; + })(FetchMethod || (FetchMethod = {})); + function fetchMethodFromString(method) { + switch (method.toLowerCase()) { + case "get": + return FetchMethod.get; + case "post": + return FetchMethod.post; + case "put": + return FetchMethod.put; + case "patch": + return FetchMethod.patch; + case "delete": + return FetchMethod.delete; } - elementFromNode(node) { - if (node.nodeType == Node.ELEMENT_NODE) { - return node; - } + } + var FetchRequest = class { + constructor(delegate, method, location2, body = new URLSearchParams(), target = null) { + this.abortController = new AbortController(); + this.resolveRequestPromise = (_value) => { + }; + this.delegate = delegate; + this.method = method; + this.headers = this.defaultHeaders; + this.body = body; + this.url = location2; + this.target = target; } - elementIsActive(element) { - if (element.isConnected != this.element.isConnected) { - return false; - } else { - return this.element.contains(element); - } + get location() { + return this.url; } - addElement(element) { - if (!this.elements.has(element)) { - if (this.elementIsActive(element)) { - this.elements.add(element); - if (this.delegate.elementMatched) { - this.delegate.elementMatched(element); + get params() { + return this.url.searchParams; + } + get entries() { + return this.body ? Array.from(this.body.entries()) : []; + } + cancel() { + this.abortController.abort(); + } + async perform() { + const { fetchOptions } = this; + this.delegate.prepareRequest(this); + await this.allowRequestToBeIntercepted(fetchOptions); + try { + this.delegate.requestStarted(this); + const response = await fetch(this.url.href, fetchOptions); + return await this.receive(response); + } catch (error2) { + if (error2.name !== "AbortError") { + if (this.willDelegateErrorHandling(error2)) { + this.delegate.requestErrored(this, error2); } + throw error2; } + } finally { + this.delegate.requestFinished(this); } } - removeElement(element) { - if (this.elements.has(element)) { - this.elements.delete(element); - if (this.delegate.elementUnmatched) { - this.delegate.elementUnmatched(element); - } + async receive(response) { + const fetchResponse = new FetchResponse(response); + const event = dispatch("turbo:before-fetch-response", { + cancelable: true, + detail: { fetchResponse }, + target: this.target + }); + if (event.defaultPrevented) { + this.delegate.requestPreventedHandlingResponse(this, fetchResponse); + } else if (fetchResponse.succeeded) { + this.delegate.requestSucceededWithResponse(this, fetchResponse); + } else { + this.delegate.requestFailedWithResponse(this, fetchResponse); } + return fetchResponse; } - }; - var AttributeObserver = class { - constructor(element, attributeName, delegate) { - this.attributeName = attributeName; - this.delegate = delegate; - this.elementObserver = new ElementObserver(element, this); - } - get element() { - return this.elementObserver.element; - } - get selector() { - return `[${this.attributeName}]`; + get fetchOptions() { + var _a; + return { + method: FetchMethod[this.method].toUpperCase(), + credentials: "same-origin", + headers: this.headers, + redirect: "follow", + body: this.isSafe ? null : this.body, + signal: this.abortSignal, + referrer: (_a = this.delegate.referrer) === null || _a === void 0 ? void 0 : _a.href + }; } - start() { - this.elementObserver.start(); + get defaultHeaders() { + return { + Accept: "text/html, application/xhtml+xml" + }; } - pause(callback) { - this.elementObserver.pause(callback); + get isSafe() { + return this.method === FetchMethod.get; } - stop() { - this.elementObserver.stop(); + get abortSignal() { + return this.abortController.signal; } - refresh() { - this.elementObserver.refresh(); + acceptResponseType(mimeType) { + this.headers["Accept"] = [mimeType, this.headers["Accept"]].join(", "); } - get started() { - return this.elementObserver.started; + async allowRequestToBeIntercepted(fetchOptions) { + const requestInterception = new Promise((resolve) => this.resolveRequestPromise = resolve); + const event = dispatch("turbo:before-fetch-request", { + cancelable: true, + detail: { + fetchOptions, + url: this.url, + resume: this.resolveRequestPromise + }, + target: this.target + }); + if (event.defaultPrevented) + await requestInterception; } - matchElement(element) { - return element.hasAttribute(this.attributeName); + willDelegateErrorHandling(error2) { + const event = dispatch("turbo:fetch-request-error", { + target: this.target, + cancelable: true, + detail: { request: this, error: error2 } + }); + return !event.defaultPrevented; } - matchElementsInTree(tree) { - const match = this.matchElement(tree) ? [tree] : []; - const matches = Array.from(tree.querySelectorAll(this.selector)); - return match.concat(matches); + }; + var AppearanceObserver = class { + constructor(delegate, element) { + this.started = false; + this.intersect = (entries) => { + const lastEntry = entries.slice(-1)[0]; + if (lastEntry === null || lastEntry === void 0 ? void 0 : lastEntry.isIntersecting) { + this.delegate.elementAppearedInViewport(this.element); + } + }; + this.delegate = delegate; + this.element = element; + this.intersectionObserver = new IntersectionObserver(this.intersect); } - elementMatched(element) { - if (this.delegate.elementMatchedAttribute) { - this.delegate.elementMatchedAttribute(element, this.attributeName); + start() { + if (!this.started) { + this.started = true; + this.intersectionObserver.observe(this.element); } } - elementUnmatched(element) { - if (this.delegate.elementUnmatchedAttribute) { - this.delegate.elementUnmatchedAttribute(element, this.attributeName); + stop() { + if (this.started) { + this.started = false; + this.intersectionObserver.unobserve(this.element); } } - elementAttributeChanged(element, attributeName) { - if (this.delegate.elementAttributeValueChanged && this.attributeName == attributeName) { - this.delegate.elementAttributeValueChanged(element, attributeName); + }; + var StreamMessage = class { + static wrap(message) { + if (typeof message == "string") { + return new this(createDocumentFragment(message)); + } else { + return message; } } + constructor(fragment) { + this.fragment = importStreamElements(fragment); + } }; - function add(map, key, value) { - fetch2(map, key).add(value); - } - function del(map, key, value) { - fetch2(map, key).delete(value); - prune(map, key); - } - function fetch2(map, key) { - let values = map.get(key); - if (!values) { - values = /* @__PURE__ */ new Set(); - map.set(key, values); + StreamMessage.contentType = "text/vnd.turbo-stream.html"; + function importStreamElements(fragment) { + for (const element of fragment.querySelectorAll("turbo-stream")) { + const streamElement = document.importNode(element, true); + for (const inertScriptElement of streamElement.templateElement.content.querySelectorAll("script")) { + inertScriptElement.replaceWith(activateScriptElement(inertScriptElement)); + } + element.replaceWith(streamElement); } - return values; + return fragment; } - function prune(map, key) { - const values = map.get(key); - if (values != null && values.size == 0) { - map.delete(key); + var FormSubmissionState; + (function(FormSubmissionState2) { + FormSubmissionState2[FormSubmissionState2["initialized"] = 0] = "initialized"; + FormSubmissionState2[FormSubmissionState2["requesting"] = 1] = "requesting"; + FormSubmissionState2[FormSubmissionState2["waiting"] = 2] = "waiting"; + FormSubmissionState2[FormSubmissionState2["receiving"] = 3] = "receiving"; + FormSubmissionState2[FormSubmissionState2["stopping"] = 4] = "stopping"; + FormSubmissionState2[FormSubmissionState2["stopped"] = 5] = "stopped"; + })(FormSubmissionState || (FormSubmissionState = {})); + var FormEnctype; + (function(FormEnctype2) { + FormEnctype2["urlEncoded"] = "application/x-www-form-urlencoded"; + FormEnctype2["multipart"] = "multipart/form-data"; + FormEnctype2["plain"] = "text/plain"; + })(FormEnctype || (FormEnctype = {})); + function formEnctypeFromString(encoding) { + switch (encoding.toLowerCase()) { + case FormEnctype.multipart: + return FormEnctype.multipart; + case FormEnctype.plain: + return FormEnctype.plain; + default: + return FormEnctype.urlEncoded; } } - var Multimap = class { - constructor() { - this.valuesByKey = /* @__PURE__ */ new Map(); + var FormSubmission = class { + static confirmMethod(message, _element, _submitter) { + return Promise.resolve(confirm(message)); } - get keys() { - return Array.from(this.valuesByKey.keys()); + constructor(delegate, formElement, submitter, mustRedirect = false) { + this.state = FormSubmissionState.initialized; + this.delegate = delegate; + this.formElement = formElement; + this.submitter = submitter; + this.formData = buildFormData(formElement, submitter); + this.location = expandURL(this.action); + if (this.method == FetchMethod.get) { + mergeFormDataEntries(this.location, [...this.body.entries()]); + } + this.fetchRequest = new FetchRequest(this, this.method, this.location, this.body, this.formElement); + this.mustRedirect = mustRedirect; } - get values() { - const sets = Array.from(this.valuesByKey.values()); - return sets.reduce((values, set) => values.concat(Array.from(set)), []); + get method() { + var _a; + const method = ((_a = this.submitter) === null || _a === void 0 ? void 0 : _a.getAttribute("formmethod")) || this.formElement.getAttribute("method") || ""; + return fetchMethodFromString(method.toLowerCase()) || FetchMethod.get; } - get size() { - const sets = Array.from(this.valuesByKey.values()); - return sets.reduce((size, set) => size + set.size, 0); + get action() { + var _a; + const formElementAction = typeof this.formElement.action === "string" ? this.formElement.action : null; + if ((_a = this.submitter) === null || _a === void 0 ? void 0 : _a.hasAttribute("formaction")) { + return this.submitter.getAttribute("formaction") || ""; + } else { + return this.formElement.getAttribute("action") || formElementAction || ""; + } } - add(key, value) { - add(this.valuesByKey, key, value); + get body() { + if (this.enctype == FormEnctype.urlEncoded || this.method == FetchMethod.get) { + return new URLSearchParams(this.stringFormData); + } else { + return this.formData; + } } - delete(key, value) { - del(this.valuesByKey, key, value); + get enctype() { + var _a; + return formEnctypeFromString(((_a = this.submitter) === null || _a === void 0 ? void 0 : _a.getAttribute("formenctype")) || this.formElement.enctype); } - has(key, value) { - const values = this.valuesByKey.get(key); - return values != null && values.has(value); + get isSafe() { + return this.fetchRequest.isSafe; } - hasKey(key) { - return this.valuesByKey.has(key); + get stringFormData() { + return [...this.formData].reduce((entries, [name, value]) => { + return entries.concat(typeof value == "string" ? [[name, value]] : []); + }, []); } - hasValue(value) { - const sets = Array.from(this.valuesByKey.values()); - return sets.some((set) => set.has(value)); + async start() { + const { initialized, requesting } = FormSubmissionState; + const confirmationMessage = getAttribute("data-turbo-confirm", this.submitter, this.formElement); + if (typeof confirmationMessage === "string") { + const answer = await FormSubmission.confirmMethod(confirmationMessage, this.formElement, this.submitter); + if (!answer) { + return; + } + } + if (this.state == initialized) { + this.state = requesting; + return this.fetchRequest.perform(); + } } - getValuesForKey(key) { - const values = this.valuesByKey.get(key); - return values ? Array.from(values) : []; + stop() { + const { stopping, stopped } = FormSubmissionState; + if (this.state != stopping && this.state != stopped) { + this.state = stopping; + this.fetchRequest.cancel(); + return true; + } } - getKeysForValue(value) { - return Array.from(this.valuesByKey).filter(([_key, values]) => values.has(value)).map(([key, _values]) => key); + prepareRequest(request) { + if (!request.isSafe) { + const token = getCookieValue(getMetaContent("csrf-param")) || getMetaContent("csrf-token"); + if (token) { + request.headers["X-CSRF-Token"] = token; + } + } + if (this.requestAcceptsTurboStreamResponse(request)) { + request.acceptResponseType(StreamMessage.contentType); + } } - }; - var SelectorObserver = class { - constructor(element, selector, delegate, details = {}) { - this.selector = selector; - this.details = details; - this.elementObserver = new ElementObserver(element, this); - this.delegate = delegate; - this.matchesByElement = new Multimap(); + requestStarted(_request) { + var _a; + this.state = FormSubmissionState.waiting; + (_a = this.submitter) === null || _a === void 0 ? void 0 : _a.setAttribute("disabled", ""); + this.setSubmitsWith(); + dispatch("turbo:submit-start", { + target: this.formElement, + detail: { formSubmission: this } + }); + this.delegate.formSubmissionStarted(this); } - get started() { - return this.elementObserver.started; + requestPreventedHandlingResponse(request, response) { + this.result = { success: response.succeeded, fetchResponse: response }; } - start() { - this.elementObserver.start(); + requestSucceededWithResponse(request, response) { + if (response.clientError || response.serverError) { + this.delegate.formSubmissionFailedWithResponse(this, response); + } else if (this.requestMustRedirect(request) && responseSucceededWithoutRedirect(response)) { + const error2 = new Error("Form responses must redirect to another location"); + this.delegate.formSubmissionErrored(this, error2); + } else { + this.state = FormSubmissionState.receiving; + this.result = { success: true, fetchResponse: response }; + this.delegate.formSubmissionSucceededWithResponse(this, response); + } } - pause(callback) { - this.elementObserver.pause(callback); + requestFailedWithResponse(request, response) { + this.result = { success: false, fetchResponse: response }; + this.delegate.formSubmissionFailedWithResponse(this, response); } - stop() { - this.elementObserver.stop(); + requestErrored(request, error2) { + this.result = { success: false, error: error2 }; + this.delegate.formSubmissionErrored(this, error2); } - refresh() { - this.elementObserver.refresh(); + requestFinished(_request) { + var _a; + this.state = FormSubmissionState.stopped; + (_a = this.submitter) === null || _a === void 0 ? void 0 : _a.removeAttribute("disabled"); + this.resetSubmitterText(); + dispatch("turbo:submit-end", { + target: this.formElement, + detail: Object.assign({ formSubmission: this }, this.result) + }); + this.delegate.formSubmissionFinished(this); } - get element() { - return this.elementObserver.element; + setSubmitsWith() { + if (!this.submitter || !this.submitsWith) + return; + if (this.submitter.matches("button")) { + this.originalSubmitText = this.submitter.innerHTML; + this.submitter.innerHTML = this.submitsWith; + } else if (this.submitter.matches("input")) { + const input = this.submitter; + this.originalSubmitText = input.value; + input.value = this.submitsWith; + } } - matchElement(element) { - const matches = element.matches(this.selector); - if (this.delegate.selectorMatchElement) { - return matches && this.delegate.selectorMatchElement(element, this.details); + resetSubmitterText() { + if (!this.submitter || !this.originalSubmitText) + return; + if (this.submitter.matches("button")) { + this.submitter.innerHTML = this.originalSubmitText; + } else if (this.submitter.matches("input")) { + const input = this.submitter; + input.value = this.originalSubmitText; } - return matches; } - matchElementsInTree(tree) { - const match = this.matchElement(tree) ? [tree] : []; - const matches = Array.from(tree.querySelectorAll(this.selector)).filter((match2) => this.matchElement(match2)); - return match.concat(matches); + requestMustRedirect(request) { + return !request.isSafe && this.mustRedirect; } - elementMatched(element) { - this.selectorMatched(element); + requestAcceptsTurboStreamResponse(request) { + return !request.isSafe || hasAttribute("data-turbo-stream", this.submitter, this.formElement); } - elementUnmatched(element) { - this.selectorUnmatched(element); + get submitsWith() { + var _a; + return (_a = this.submitter) === null || _a === void 0 ? void 0 : _a.getAttribute("data-turbo-submits-with"); } - elementAttributeChanged(element, _attributeName) { - const matches = this.matchElement(element); - const matchedBefore = this.matchesByElement.has(this.selector, element); - if (!matches && matchedBefore) { - this.selectorUnmatched(element); - } + }; + function buildFormData(formElement, submitter) { + const formData = new FormData(formElement); + const name = submitter === null || submitter === void 0 ? void 0 : submitter.getAttribute("name"); + const value = submitter === null || submitter === void 0 ? void 0 : submitter.getAttribute("value"); + if (name) { + formData.append(name, value || ""); } - selectorMatched(element) { - if (this.delegate.selectorMatched) { - this.delegate.selectorMatched(element, this.selector, this.details); - this.matchesByElement.add(this.selector, element); + return formData; + } + function getCookieValue(cookieName) { + if (cookieName != null) { + const cookies = document.cookie ? document.cookie.split("; ") : []; + const cookie = cookies.find((cookie2) => cookie2.startsWith(cookieName)); + if (cookie) { + const value = cookie.split("=").slice(1).join("="); + return value ? decodeURIComponent(value) : void 0; } } - selectorUnmatched(element) { - this.delegate.selectorUnmatched(element, this.selector, this.details); - this.matchesByElement.delete(this.selector, element); + } + function responseSucceededWithoutRedirect(response) { + return response.statusCode == 200 && !response.redirected; + } + function mergeFormDataEntries(url, entries) { + const searchParams = new URLSearchParams(); + for (const [name, value] of entries) { + if (value instanceof File) + continue; + searchParams.append(name, value); } - }; - var StringMapObserver = class { - constructor(element, delegate) { + url.search = searchParams.toString(); + return url; + } + var Snapshot = class { + constructor(element) { this.element = element; - this.delegate = delegate; - this.started = false; - this.stringMap = /* @__PURE__ */ new Map(); - this.mutationObserver = new MutationObserver((mutations) => this.processMutations(mutations)); } - start() { - if (!this.started) { - this.started = true; - this.mutationObserver.observe(this.element, { attributes: true, attributeOldValue: true }); - this.refresh(); - } + get activeElement() { + return this.element.ownerDocument.activeElement; } - stop() { - if (this.started) { - this.mutationObserver.takeRecords(); - this.mutationObserver.disconnect(); - this.started = false; - } + get children() { + return [...this.element.children]; } - refresh() { - if (this.started) { - for (const attributeName of this.knownAttributeNames) { - this.refreshAttribute(attributeName, null); - } - } + hasAnchor(anchor) { + return this.getElementForAnchor(anchor) != null; } - processMutations(mutations) { - if (this.started) { - for (const mutation of mutations) { - this.processMutation(mutation); - } - } + getElementForAnchor(anchor) { + return anchor ? this.element.querySelector(`[id='${anchor}'], a[name='${anchor}']`) : null; } - processMutation(mutation) { - const attributeName = mutation.attributeName; - if (attributeName) { - this.refreshAttribute(attributeName, mutation.oldValue); - } + get isConnected() { + return this.element.isConnected; } - refreshAttribute(attributeName, oldValue) { - const key = this.delegate.getStringMapKeyForAttribute(attributeName); - if (key != null) { - if (!this.stringMap.has(attributeName)) { - this.stringMapKeyAdded(key, attributeName); - } - const value = this.element.getAttribute(attributeName); - if (this.stringMap.get(attributeName) != value) { - this.stringMapValueChanged(value, key, oldValue); - } - if (value == null) { - const oldValue2 = this.stringMap.get(attributeName); - this.stringMap.delete(attributeName); - if (oldValue2) - this.stringMapKeyRemoved(key, attributeName, oldValue2); - } else { - this.stringMap.set(attributeName, value); - } + get firstAutofocusableElement() { + const inertDisabledOrHidden = "[inert], :disabled, [hidden], details:not([open]), dialog:not([open])"; + for (const element of this.element.querySelectorAll("[autofocus]")) { + if (element.closest(inertDisabledOrHidden) == null) + return element; + else + continue; } + return null; } - stringMapKeyAdded(key, attributeName) { - if (this.delegate.stringMapKeyAdded) { - this.delegate.stringMapKeyAdded(key, attributeName); - } + get permanentElements() { + return queryPermanentElementsAll(this.element); } - stringMapValueChanged(value, key, oldValue) { - if (this.delegate.stringMapValueChanged) { - this.delegate.stringMapValueChanged(value, key, oldValue); - } + getPermanentElementById(id) { + return getPermanentElementById(this.element, id); } - stringMapKeyRemoved(key, attributeName, oldValue) { - if (this.delegate.stringMapKeyRemoved) { - this.delegate.stringMapKeyRemoved(key, attributeName, oldValue); + getPermanentElementMapForSnapshot(snapshot) { + const permanentElementMap = {}; + for (const currentPermanentElement of this.permanentElements) { + const { id } = currentPermanentElement; + const newPermanentElement = snapshot.getPermanentElementById(id); + if (newPermanentElement) { + permanentElementMap[id] = [currentPermanentElement, newPermanentElement]; + } } - } - get knownAttributeNames() { - return Array.from(new Set(this.currentAttributeNames.concat(this.recordedAttributeNames))); - } - get currentAttributeNames() { - return Array.from(this.element.attributes).map((attribute) => attribute.name); - } - get recordedAttributeNames() { - return Array.from(this.stringMap.keys()); + return permanentElementMap; } }; - var TokenListObserver = class { - constructor(element, attributeName, delegate) { - this.attributeObserver = new AttributeObserver(element, attributeName, this); + function getPermanentElementById(node, id) { + return node.querySelector(`#${id}[data-turbo-permanent]`); + } + function queryPermanentElementsAll(node) { + return node.querySelectorAll("[id][data-turbo-permanent]"); + } + var FormSubmitObserver = class { + constructor(delegate, eventTarget) { + this.started = false; + this.submitCaptured = () => { + this.eventTarget.removeEventListener("submit", this.submitBubbled, false); + this.eventTarget.addEventListener("submit", this.submitBubbled, false); + }; + this.submitBubbled = (event) => { + if (!event.defaultPrevented) { + const form = event.target instanceof HTMLFormElement ? event.target : void 0; + const submitter = event.submitter || void 0; + if (form && submissionDoesNotDismissDialog(form, submitter) && submissionDoesNotTargetIFrame(form, submitter) && this.delegate.willSubmitForm(form, submitter)) { + event.preventDefault(); + event.stopImmediatePropagation(); + this.delegate.formSubmitted(form, submitter); + } + } + }; this.delegate = delegate; - this.tokensByElement = new Multimap(); - } - get started() { - return this.attributeObserver.started; + this.eventTarget = eventTarget; } start() { - this.attributeObserver.start(); - } - pause(callback) { - this.attributeObserver.pause(callback); + if (!this.started) { + this.eventTarget.addEventListener("submit", this.submitCaptured, true); + this.started = true; + } } stop() { - this.attributeObserver.stop(); - } - refresh() { - this.attributeObserver.refresh(); + if (this.started) { + this.eventTarget.removeEventListener("submit", this.submitCaptured, true); + this.started = false; + } } - get element() { - return this.attributeObserver.element; + }; + function submissionDoesNotDismissDialog(form, submitter) { + const method = (submitter === null || submitter === void 0 ? void 0 : submitter.getAttribute("formmethod")) || form.getAttribute("method"); + return method != "dialog"; + } + function submissionDoesNotTargetIFrame(form, submitter) { + if ((submitter === null || submitter === void 0 ? void 0 : submitter.hasAttribute("formtarget")) || form.hasAttribute("target")) { + const target = (submitter === null || submitter === void 0 ? void 0 : submitter.getAttribute("formtarget")) || form.target; + for (const element of document.getElementsByName(target)) { + if (element instanceof HTMLIFrameElement) + return false; + } + return true; + } else { + return true; } - get attributeName() { - return this.attributeObserver.attributeName; + } + var View = class { + constructor(delegate, element) { + this.resolveRenderPromise = (_value) => { + }; + this.resolveInterceptionPromise = (_value) => { + }; + this.delegate = delegate; + this.element = element; } - elementMatchedAttribute(element) { - this.tokensMatched(this.readTokensForElement(element)); + scrollToAnchor(anchor) { + const element = this.snapshot.getElementForAnchor(anchor); + if (element) { + this.scrollToElement(element); + this.focusElement(element); + } else { + this.scrollToPosition({ x: 0, y: 0 }); + } } - elementAttributeValueChanged(element) { - const [unmatchedTokens, matchedTokens] = this.refreshTokensForElement(element); - this.tokensUnmatched(unmatchedTokens); - this.tokensMatched(matchedTokens); + scrollToAnchorFromLocation(location2) { + this.scrollToAnchor(getAnchor(location2)); } - elementUnmatchedAttribute(element) { - this.tokensUnmatched(this.tokensByElement.getValuesForKey(element)); + scrollToElement(element) { + element.scrollIntoView(); } - tokensMatched(tokens) { - tokens.forEach((token) => this.tokenMatched(token)); + focusElement(element) { + if (element instanceof HTMLElement) { + if (element.hasAttribute("tabindex")) { + element.focus(); + } else { + element.setAttribute("tabindex", "-1"); + element.focus(); + element.removeAttribute("tabindex"); + } + } } - tokensUnmatched(tokens) { - tokens.forEach((token) => this.tokenUnmatched(token)); + scrollToPosition({ x, y }) { + this.scrollRoot.scrollTo(x, y); } - tokenMatched(token) { - this.delegate.tokenMatched(token); - this.tokensByElement.add(token.element, token); + scrollToTop() { + this.scrollToPosition({ x: 0, y: 0 }); } - tokenUnmatched(token) { - this.delegate.tokenUnmatched(token); - this.tokensByElement.delete(token.element, token); + get scrollRoot() { + return window; } - refreshTokensForElement(element) { - const previousTokens = this.tokensByElement.getValuesForKey(element); - const currentTokens = this.readTokensForElement(element); - const firstDifferingIndex = zip(previousTokens, currentTokens).findIndex(([previousToken, currentToken]) => !tokensAreEqual(previousToken, currentToken)); - if (firstDifferingIndex == -1) { - return [[], []]; + async render(renderer) { + const { isPreview, shouldRender, newSnapshot: snapshot } = renderer; + if (shouldRender) { + try { + this.renderPromise = new Promise((resolve) => this.resolveRenderPromise = resolve); + this.renderer = renderer; + await this.prepareToRenderSnapshot(renderer); + const renderInterception = new Promise((resolve) => this.resolveInterceptionPromise = resolve); + const options = { resume: this.resolveInterceptionPromise, render: this.renderer.renderElement }; + const immediateRender = this.delegate.allowsImmediateRender(snapshot, options); + if (!immediateRender) + await renderInterception; + await this.renderSnapshot(renderer); + this.delegate.viewRenderedSnapshot(snapshot, isPreview); + this.delegate.preloadOnLoadLinksForView(this.element); + this.finishRenderingSnapshot(renderer); + } finally { + delete this.renderer; + this.resolveRenderPromise(void 0); + delete this.renderPromise; + } } else { - return [previousTokens.slice(firstDifferingIndex), currentTokens.slice(firstDifferingIndex)]; + this.invalidate(renderer.reloadReason); } } - readTokensForElement(element) { - const attributeName = this.attributeName; - const tokenString = element.getAttribute(attributeName) || ""; - return parseTokenString(tokenString, element, attributeName); + invalidate(reason) { + this.delegate.viewInvalidated(reason); } - }; - function parseTokenString(tokenString, element, attributeName) { - return tokenString.trim().split(/\s+/).filter((content) => content.length).map((content, index) => ({ element, attributeName, content, index })); - } - function zip(left, right) { - const length = Math.max(left.length, right.length); - return Array.from({ length }, (_, index) => [left[index], right[index]]); - } - function tokensAreEqual(left, right) { - return left && right && left.index == right.index && left.content == right.content; - } - var ValueListObserver = class { - constructor(element, attributeName, delegate) { - this.tokenListObserver = new TokenListObserver(element, attributeName, this); - this.delegate = delegate; - this.parseResultsByToken = /* @__PURE__ */ new WeakMap(); - this.valuesByTokenByElement = /* @__PURE__ */ new WeakMap(); + async prepareToRenderSnapshot(renderer) { + this.markAsPreview(renderer.isPreview); + await renderer.prepareToRender(); } - get started() { - return this.tokenListObserver.started; + markAsPreview(isPreview) { + if (isPreview) { + this.element.setAttribute("data-turbo-preview", ""); + } else { + this.element.removeAttribute("data-turbo-preview"); + } } - start() { - this.tokenListObserver.start(); + async renderSnapshot(renderer) { + await renderer.render(); } - stop() { - this.tokenListObserver.stop(); + finishRenderingSnapshot(renderer) { + renderer.finishRendering(); } - refresh() { - this.tokenListObserver.refresh(); - } - get element() { - return this.tokenListObserver.element; - } - get attributeName() { - return this.tokenListObserver.attributeName; + }; + var FrameView = class extends View { + missing() { + this.element.innerHTML = `Content missing`; } - tokenMatched(token) { - const { element } = token; - const { value } = this.fetchParseResultForToken(token); - if (value) { - this.fetchValuesByTokenForElement(element).set(token, value); - this.delegate.elementMatchedValue(element, value); - } + get snapshot() { + return new Snapshot(this.element); } - tokenUnmatched(token) { - const { element } = token; - const { value } = this.fetchParseResultForToken(token); - if (value) { - this.fetchValuesByTokenForElement(element).delete(token); - this.delegate.elementUnmatchedValue(element, value); - } + }; + var LinkInterceptor = class { + constructor(delegate, element) { + this.clickBubbled = (event) => { + if (this.respondsToEventTarget(event.target)) { + this.clickEvent = event; + } else { + delete this.clickEvent; + } + }; + this.linkClicked = (event) => { + if (this.clickEvent && this.respondsToEventTarget(event.target) && event.target instanceof Element) { + if (this.delegate.shouldInterceptLinkClick(event.target, event.detail.url, event.detail.originalEvent)) { + this.clickEvent.preventDefault(); + event.preventDefault(); + this.delegate.linkClickIntercepted(event.target, event.detail.url, event.detail.originalEvent); + } + } + delete this.clickEvent; + }; + this.willVisit = (_event) => { + delete this.clickEvent; + }; + this.delegate = delegate; + this.element = element; } - fetchParseResultForToken(token) { - let parseResult = this.parseResultsByToken.get(token); - if (!parseResult) { - parseResult = this.parseToken(token); - this.parseResultsByToken.set(token, parseResult); - } - return parseResult; + start() { + this.element.addEventListener("click", this.clickBubbled); + document.addEventListener("turbo:click", this.linkClicked); + document.addEventListener("turbo:before-visit", this.willVisit); } - fetchValuesByTokenForElement(element) { - let valuesByToken = this.valuesByTokenByElement.get(element); - if (!valuesByToken) { - valuesByToken = /* @__PURE__ */ new Map(); - this.valuesByTokenByElement.set(element, valuesByToken); - } - return valuesByToken; + stop() { + this.element.removeEventListener("click", this.clickBubbled); + document.removeEventListener("turbo:click", this.linkClicked); + document.removeEventListener("turbo:before-visit", this.willVisit); } - parseToken(token) { - try { - const value = this.delegate.parseValueForToken(token); - return { value }; - } catch (error2) { - return { error: error2 }; - } + respondsToEventTarget(target) { + const element = target instanceof Element ? target : target instanceof Node ? target.parentElement : null; + return element && element.closest("turbo-frame, html") == this.element; } }; - var BindingObserver = class { - constructor(context, delegate) { - this.context = context; + var LinkClickObserver = class { + constructor(delegate, eventTarget) { + this.started = false; + this.clickCaptured = () => { + this.eventTarget.removeEventListener("click", this.clickBubbled, false); + this.eventTarget.addEventListener("click", this.clickBubbled, false); + }; + this.clickBubbled = (event) => { + if (event instanceof MouseEvent && this.clickEventIsSignificant(event)) { + const target = event.composedPath && event.composedPath()[0] || event.target; + const link = this.findLinkFromClickTarget(target); + if (link && doesNotTargetIFrame(link)) { + const location2 = this.getLocationForLink(link); + if (this.delegate.willFollowLinkToLocation(link, location2, event)) { + event.preventDefault(); + this.delegate.followedLinkToLocation(link, location2); + } + } + } + }; this.delegate = delegate; - this.bindingsByAction = /* @__PURE__ */ new Map(); + this.eventTarget = eventTarget; } start() { - if (!this.valueListObserver) { - this.valueListObserver = new ValueListObserver(this.element, this.actionAttribute, this); - this.valueListObserver.start(); + if (!this.started) { + this.eventTarget.addEventListener("click", this.clickCaptured, true); + this.started = true; } } stop() { - if (this.valueListObserver) { - this.valueListObserver.stop(); - delete this.valueListObserver; - this.disconnectAllActions(); + if (this.started) { + this.eventTarget.removeEventListener("click", this.clickCaptured, true); + this.started = false; } } - get element() { - return this.context.element; + clickEventIsSignificant(event) { + return !(event.target && event.target.isContentEditable || event.defaultPrevented || event.which > 1 || event.altKey || event.ctrlKey || event.metaKey || event.shiftKey); } - get identifier() { - return this.context.identifier; + findLinkFromClickTarget(target) { + return findClosestRecursively(target, "a[href]:not([target^=_]):not([download])"); } - get actionAttribute() { - return this.schema.actionAttribute; + getLocationForLink(link) { + return expandURL(link.getAttribute("href") || ""); } - get schema() { - return this.context.schema; + }; + function doesNotTargetIFrame(anchor) { + if (anchor.hasAttribute("target")) { + for (const element of document.getElementsByName(anchor.target)) { + if (element instanceof HTMLIFrameElement) + return false; + } + return true; + } else { + return true; } - get bindings() { - return Array.from(this.bindingsByAction.values()); + } + var FormLinkClickObserver = class { + constructor(delegate, element) { + this.delegate = delegate; + this.linkInterceptor = new LinkClickObserver(this, element); } - connectAction(action) { - const binding = new Binding(this.context, action); - this.bindingsByAction.set(action, binding); - this.delegate.bindingConnected(binding); + start() { + this.linkInterceptor.start(); } - disconnectAction(action) { - const binding = this.bindingsByAction.get(action); - if (binding) { - this.bindingsByAction.delete(action); - this.delegate.bindingDisconnected(binding); - } + stop() { + this.linkInterceptor.stop(); } - disconnectAllActions() { - this.bindings.forEach((binding) => this.delegate.bindingDisconnected(binding, true)); - this.bindingsByAction.clear(); + willFollowLinkToLocation(link, location2, originalEvent) { + return this.delegate.willSubmitFormLinkToLocation(link, location2, originalEvent) && link.hasAttribute("data-turbo-method"); } - parseValueForToken(token) { - const action = Action.forToken(token, this.schema); - if (action.identifier == this.identifier) { - return action; + followedLinkToLocation(link, location2) { + const form = document.createElement("form"); + const type = "hidden"; + for (const [name, value] of location2.searchParams) { + form.append(Object.assign(document.createElement("input"), { type, name, value })); } - } - elementMatchedValue(element, action) { - this.connectAction(action); - } - elementUnmatchedValue(element, action) { - this.disconnectAction(action); + const action = Object.assign(location2, { search: "" }); + form.setAttribute("data-turbo", "true"); + form.setAttribute("action", action.href); + form.setAttribute("hidden", ""); + const method = link.getAttribute("data-turbo-method"); + if (method) + form.setAttribute("method", method); + const turboFrame = link.getAttribute("data-turbo-frame"); + if (turboFrame) + form.setAttribute("data-turbo-frame", turboFrame); + const turboAction = getVisitAction(link); + if (turboAction) + form.setAttribute("data-turbo-action", turboAction); + const turboConfirm = link.getAttribute("data-turbo-confirm"); + if (turboConfirm) + form.setAttribute("data-turbo-confirm", turboConfirm); + const turboStream = link.hasAttribute("data-turbo-stream"); + if (turboStream) + form.setAttribute("data-turbo-stream", ""); + this.delegate.submittedFormLinkToLocation(link, location2, form); + document.body.appendChild(form); + form.addEventListener("turbo:submit-end", () => form.remove(), { once: true }); + requestAnimationFrame(() => form.requestSubmit()); } }; - var ValueObserver = class { - constructor(context, receiver) { - this.context = context; - this.receiver = receiver; - this.stringMapObserver = new StringMapObserver(this.element, this); - this.valueDescriptorMap = this.controller.valueDescriptorMap; - } - start() { - this.stringMapObserver.start(); - this.invokeChangedCallbacksForDefaultValues(); - } - stop() { - this.stringMapObserver.stop(); - } - get element() { - return this.context.element; + var Bardo = class { + static async preservingPermanentElements(delegate, permanentElementMap, callback) { + const bardo = new this(delegate, permanentElementMap); + bardo.enter(); + await callback(); + bardo.leave(); } - get controller() { - return this.context.controller; + constructor(delegate, permanentElementMap) { + this.delegate = delegate; + this.permanentElementMap = permanentElementMap; } - getStringMapKeyForAttribute(attributeName) { - if (attributeName in this.valueDescriptorMap) { - return this.valueDescriptorMap[attributeName].name; + enter() { + for (const id in this.permanentElementMap) { + const [currentPermanentElement, newPermanentElement] = this.permanentElementMap[id]; + this.delegate.enteringBardo(currentPermanentElement, newPermanentElement); + this.replaceNewPermanentElementWithPlaceholder(newPermanentElement); } } - stringMapKeyAdded(key, attributeName) { - const descriptor = this.valueDescriptorMap[attributeName]; - if (!this.hasValue(key)) { - this.invokeChangedCallback(key, descriptor.writer(this.receiver[key]), descriptor.writer(descriptor.defaultValue)); + leave() { + for (const id in this.permanentElementMap) { + const [currentPermanentElement] = this.permanentElementMap[id]; + this.replaceCurrentPermanentElementWithClone(currentPermanentElement); + this.replacePlaceholderWithPermanentElement(currentPermanentElement); + this.delegate.leavingBardo(currentPermanentElement); } } - stringMapValueChanged(value, name, oldValue) { - const descriptor = this.valueDescriptorNameMap[name]; - if (value === null) - return; - if (oldValue === null) { - oldValue = descriptor.writer(descriptor.defaultValue); - } - this.invokeChangedCallback(name, value, oldValue); - } - stringMapKeyRemoved(key, attributeName, oldValue) { - const descriptor = this.valueDescriptorNameMap[key]; - if (this.hasValue(key)) { - this.invokeChangedCallback(key, descriptor.writer(this.receiver[key]), oldValue); - } else { - this.invokeChangedCallback(key, descriptor.writer(descriptor.defaultValue), oldValue); - } - } - invokeChangedCallbacksForDefaultValues() { - for (const { key, name, defaultValue, writer } of this.valueDescriptors) { - if (defaultValue != void 0 && !this.controller.data.has(key)) { - this.invokeChangedCallback(name, writer(defaultValue), void 0); - } - } + replaceNewPermanentElementWithPlaceholder(permanentElement) { + const placeholder = createPlaceholderForPermanentElement(permanentElement); + permanentElement.replaceWith(placeholder); } - invokeChangedCallback(name, rawValue, rawOldValue) { - const changedMethodName = `${name}Changed`; - const changedMethod = this.receiver[changedMethodName]; - if (typeof changedMethod == "function") { - const descriptor = this.valueDescriptorNameMap[name]; - try { - const value = descriptor.reader(rawValue); - let oldValue = rawOldValue; - if (rawOldValue) { - oldValue = descriptor.reader(rawOldValue); - } - changedMethod.call(this.receiver, value, oldValue); - } catch (error2) { - if (error2 instanceof TypeError) { - error2.message = `Stimulus Value "${this.context.identifier}.${descriptor.name}" - ${error2.message}`; - } - throw error2; - } - } + replaceCurrentPermanentElementWithClone(permanentElement) { + const clone = permanentElement.cloneNode(true); + permanentElement.replaceWith(clone); } - get valueDescriptors() { - const { valueDescriptorMap } = this; - return Object.keys(valueDescriptorMap).map((key) => valueDescriptorMap[key]); + replacePlaceholderWithPermanentElement(permanentElement) { + const placeholder = this.getPlaceholderById(permanentElement.id); + placeholder === null || placeholder === void 0 ? void 0 : placeholder.replaceWith(permanentElement); } - get valueDescriptorNameMap() { - const descriptors = {}; - Object.keys(this.valueDescriptorMap).forEach((key) => { - const descriptor = this.valueDescriptorMap[key]; - descriptors[descriptor.name] = descriptor; - }); - return descriptors; + getPlaceholderById(id) { + return this.placeholders.find((element) => element.content == id); } - hasValue(attributeName) { - const descriptor = this.valueDescriptorNameMap[attributeName]; - const hasMethodName = `has${capitalize(descriptor.name)}`; - return this.receiver[hasMethodName]; + get placeholders() { + return [...document.querySelectorAll("meta[name=turbo-permanent-placeholder][content]")]; } }; - var TargetObserver = class { - constructor(context, delegate) { - this.context = context; - this.delegate = delegate; - this.targetsByName = new Multimap(); + function createPlaceholderForPermanentElement(permanentElement) { + const element = document.createElement("meta"); + element.setAttribute("name", "turbo-permanent-placeholder"); + element.setAttribute("content", permanentElement.id); + return element; + } + var Renderer = class { + constructor(currentSnapshot, newSnapshot, renderElement, isPreview, willRender = true) { + this.activeElement = null; + this.currentSnapshot = currentSnapshot; + this.newSnapshot = newSnapshot; + this.isPreview = isPreview; + this.willRender = willRender; + this.renderElement = renderElement; + this.promise = new Promise((resolve, reject) => this.resolvingFunctions = { resolve, reject }); } - start() { - if (!this.tokenListObserver) { - this.tokenListObserver = new TokenListObserver(this.element, this.attributeName, this); - this.tokenListObserver.start(); - } + get shouldRender() { + return true; } - stop() { - if (this.tokenListObserver) { - this.disconnectAllTargets(); - this.tokenListObserver.stop(); - delete this.tokenListObserver; - } + get reloadReason() { + return; } - tokenMatched({ element, content: name }) { - if (this.scope.containsElement(element)) { - this.connectTarget(element, name); + prepareToRender() { + return; + } + finishRendering() { + if (this.resolvingFunctions) { + this.resolvingFunctions.resolve(); + delete this.resolvingFunctions; } } - tokenUnmatched({ element, content: name }) { - this.disconnectTarget(element, name); + async preservingPermanentElements(callback) { + await Bardo.preservingPermanentElements(this, this.permanentElementMap, callback); } - connectTarget(element, name) { - var _a; - if (!this.targetsByName.has(name, element)) { - this.targetsByName.add(name, element); - (_a = this.tokenListObserver) === null || _a === void 0 ? void 0 : _a.pause(() => this.delegate.targetConnected(element, name)); + focusFirstAutofocusableElement() { + const element = this.connectedSnapshot.firstAutofocusableElement; + if (elementIsFocusable(element)) { + element.focus(); } } - disconnectTarget(element, name) { - var _a; - if (this.targetsByName.has(name, element)) { - this.targetsByName.delete(name, element); - (_a = this.tokenListObserver) === null || _a === void 0 ? void 0 : _a.pause(() => this.delegate.targetDisconnected(element, name)); + enteringBardo(currentPermanentElement) { + if (this.activeElement) + return; + if (currentPermanentElement.contains(this.currentSnapshot.activeElement)) { + this.activeElement = this.currentSnapshot.activeElement; } } - disconnectAllTargets() { - for (const name of this.targetsByName.keys) { - for (const element of this.targetsByName.getValuesForKey(name)) { - this.disconnectTarget(element, name); - } + leavingBardo(currentPermanentElement) { + if (currentPermanentElement.contains(this.activeElement) && this.activeElement instanceof HTMLElement) { + this.activeElement.focus(); + this.activeElement = null; } } - get attributeName() { - return `data-${this.context.identifier}-target`; + get connectedSnapshot() { + return this.newSnapshot.isConnected ? this.newSnapshot : this.currentSnapshot; } - get element() { - return this.context.element; + get currentElement() { + return this.currentSnapshot.element; } - get scope() { - return this.context.scope; + get newElement() { + return this.newSnapshot.element; + } + get permanentElementMap() { + return this.currentSnapshot.getPermanentElementMapForSnapshot(this.newSnapshot); } }; - function readInheritableStaticArrayValues(constructor, propertyName) { - const ancestors = getAncestorsForConstructor(constructor); - return Array.from(ancestors.reduce((values, constructor2) => { - getOwnStaticArrayValues(constructor2, propertyName).forEach((name) => values.add(name)); - return values; - }, /* @__PURE__ */ new Set())); - } - function readInheritableStaticObjectPairs(constructor, propertyName) { - const ancestors = getAncestorsForConstructor(constructor); - return ancestors.reduce((pairs, constructor2) => { - pairs.push(...getOwnStaticObjectPairs(constructor2, propertyName)); - return pairs; - }, []); + function elementIsFocusable(element) { + return element && typeof element.focus == "function"; } - function getAncestorsForConstructor(constructor) { - const ancestors = []; - while (constructor) { - ancestors.push(constructor); - constructor = Object.getPrototypeOf(constructor); + var FrameRenderer = class extends Renderer { + static renderElement(currentElement, newElement) { + var _a; + const destinationRange = document.createRange(); + destinationRange.selectNodeContents(currentElement); + destinationRange.deleteContents(); + const frameElement = newElement; + const sourceRange = (_a = frameElement.ownerDocument) === null || _a === void 0 ? void 0 : _a.createRange(); + if (sourceRange) { + sourceRange.selectNodeContents(frameElement); + currentElement.appendChild(sourceRange.extractContents()); + } } - return ancestors.reverse(); - } - function getOwnStaticArrayValues(constructor, propertyName) { - const definition = constructor[propertyName]; - return Array.isArray(definition) ? definition : []; - } - function getOwnStaticObjectPairs(constructor, propertyName) { - const definition = constructor[propertyName]; - return definition ? Object.keys(definition).map((key) => [key, definition[key]]) : []; - } - var OutletObserver = class { - constructor(context, delegate) { - this.context = context; + constructor(delegate, currentSnapshot, newSnapshot, renderElement, isPreview, willRender = true) { + super(currentSnapshot, newSnapshot, renderElement, isPreview, willRender); this.delegate = delegate; - this.outletsByName = new Multimap(); - this.outletElementsByName = new Multimap(); - this.selectorObserverMap = /* @__PURE__ */ new Map(); - } - start() { - if (this.selectorObserverMap.size === 0) { - this.outletDefinitions.forEach((outletName) => { - const selector = this.selector(outletName); - const details = { outletName }; - if (selector) { - this.selectorObserverMap.set(outletName, new SelectorObserver(document.body, selector, this, details)); - } - }); - this.selectorObserverMap.forEach((observer) => observer.start()); - } - this.dependentContexts.forEach((context) => context.refresh()); } - stop() { - if (this.selectorObserverMap.size > 0) { - this.disconnectAllOutlets(); - this.selectorObserverMap.forEach((observer) => observer.stop()); - this.selectorObserverMap.clear(); - } + get shouldRender() { + return true; } - refresh() { - this.selectorObserverMap.forEach((observer) => observer.refresh()); + async render() { + await nextAnimationFrame(); + this.preservingPermanentElements(() => { + this.loadFrameElement(); + }); + this.scrollFrameIntoView(); + await nextAnimationFrame(); + this.focusFirstAutofocusableElement(); + await nextAnimationFrame(); + this.activateScriptElements(); } - selectorMatched(element, _selector, { outletName }) { - const outlet = this.getOutlet(element, outletName); - if (outlet) { - this.connectOutlet(outlet, element, outletName); - } + loadFrameElement() { + this.delegate.willRenderFrame(this.currentElement, this.newElement); + this.renderElement(this.currentElement, this.newElement); } - selectorUnmatched(element, _selector, { outletName }) { - const outlet = this.getOutletFromMap(element, outletName); - if (outlet) { - this.disconnectOutlet(outlet, element, outletName); - } - } - selectorMatchElement(element, { outletName }) { - return this.hasOutlet(element, outletName) && element.matches(`[${this.context.application.schema.controllerAttribute}~=${outletName}]`); - } - connectOutlet(outlet, element, outletName) { - var _a; - if (!this.outletElementsByName.has(outletName, element)) { - this.outletsByName.add(outletName, outlet); - this.outletElementsByName.add(outletName, element); - (_a = this.selectorObserverMap.get(outletName)) === null || _a === void 0 ? void 0 : _a.pause(() => this.delegate.outletConnected(outlet, element, outletName)); - } - } - disconnectOutlet(outlet, element, outletName) { - var _a; - if (this.outletElementsByName.has(outletName, element)) { - this.outletsByName.delete(outletName, outlet); - this.outletElementsByName.delete(outletName, element); - (_a = this.selectorObserverMap.get(outletName)) === null || _a === void 0 ? void 0 : _a.pause(() => this.delegate.outletDisconnected(outlet, element, outletName)); - } - } - disconnectAllOutlets() { - for (const outletName of this.outletElementsByName.keys) { - for (const element of this.outletElementsByName.getValuesForKey(outletName)) { - for (const outlet of this.outletsByName.getValuesForKey(outletName)) { - this.disconnectOutlet(outlet, element, outletName); - } + scrollFrameIntoView() { + if (this.currentElement.autoscroll || this.newElement.autoscroll) { + const element = this.currentElement.firstElementChild; + const block = readScrollLogicalPosition(this.currentElement.getAttribute("data-autoscroll-block"), "end"); + const behavior = readScrollBehavior(this.currentElement.getAttribute("data-autoscroll-behavior"), "auto"); + if (element) { + element.scrollIntoView({ block, behavior }); + return true; } } + return false; } - selector(outletName) { - return this.scope.outlets.getSelectorForOutletName(outletName); + activateScriptElements() { + for (const inertScriptElement of this.newScriptElements) { + const activatedScriptElement = activateScriptElement(inertScriptElement); + inertScriptElement.replaceWith(activatedScriptElement); + } } - get outletDependencies() { - const dependencies = new Multimap(); - this.router.modules.forEach((module) => { - const constructor = module.definition.controllerConstructor; - const outlets = readInheritableStaticArrayValues(constructor, "outlets"); - outlets.forEach((outlet) => dependencies.add(outlet, module.identifier)); - }); - return dependencies; + get newScriptElements() { + return this.currentElement.querySelectorAll("script"); } - get outletDefinitions() { - return this.outletDependencies.getKeysForValue(this.identifier); + }; + function readScrollLogicalPosition(value, defaultValue) { + if (value == "end" || value == "start" || value == "center" || value == "nearest") { + return value; + } else { + return defaultValue; } - get dependentControllerIdentifiers() { - return this.outletDependencies.getValuesForKey(this.identifier); + } + function readScrollBehavior(value, defaultValue) { + if (value == "auto" || value == "smooth") { + return value; + } else { + return defaultValue; } - get dependentContexts() { - const identifiers = this.dependentControllerIdentifiers; - return this.router.contexts.filter((context) => identifiers.includes(context.identifier)); + } + var ProgressBar = class { + static get defaultCSS() { + return unindent` + .turbo-progress-bar { + position: fixed; + display: block; + top: 0; + left: 0; + height: 3px; + background: #0076ff; + z-index: 2147483647; + transition: + width ${ProgressBar.animationDuration}ms ease-out, + opacity ${ProgressBar.animationDuration / 2}ms ${ProgressBar.animationDuration / 2}ms ease-in; + transform: translate3d(0, 0, 0); + } + `; } - hasOutlet(element, outletName) { - return !!this.getOutlet(element, outletName) || !!this.getOutletFromMap(element, outletName); + constructor() { + this.hiding = false; + this.value = 0; + this.visible = false; + this.trickle = () => { + this.setValue(this.value + Math.random() / 100); + }; + this.stylesheetElement = this.createStylesheetElement(); + this.progressElement = this.createProgressElement(); + this.installStylesheetElement(); + this.setValue(0); } - getOutlet(element, outletName) { - return this.application.getControllerForElementAndIdentifier(element, outletName); + show() { + if (!this.visible) { + this.visible = true; + this.installProgressElement(); + this.startTrickling(); + } } - getOutletFromMap(element, outletName) { - return this.outletsByName.getValuesForKey(outletName).find((outlet) => outlet.element === element); + hide() { + if (this.visible && !this.hiding) { + this.hiding = true; + this.fadeProgressElement(() => { + this.uninstallProgressElement(); + this.stopTrickling(); + this.visible = false; + this.hiding = false; + }); + } } - get scope() { - return this.context.scope; + setValue(value) { + this.value = value; + this.refresh(); } - get identifier() { - return this.context.identifier; + installStylesheetElement() { + document.head.insertBefore(this.stylesheetElement, document.head.firstChild); } - get application() { - return this.context.application; + installProgressElement() { + this.progressElement.style.width = "0"; + this.progressElement.style.opacity = "1"; + document.documentElement.insertBefore(this.progressElement, document.body); + this.refresh(); } - get router() { - return this.application.router; + fadeProgressElement(callback) { + this.progressElement.style.opacity = "0"; + setTimeout(callback, ProgressBar.animationDuration * 1.5); } - }; - var Context = class { - constructor(module, scope) { - this.logDebugActivity = (functionName, detail = {}) => { - const { identifier, controller, element } = this; - detail = Object.assign({ identifier, controller, element }, detail); - this.application.logDebugActivity(this.identifier, functionName, detail); - }; - this.module = module; - this.scope = scope; - this.controller = new module.controllerConstructor(this); - this.bindingObserver = new BindingObserver(this, this.dispatcher); - this.valueObserver = new ValueObserver(this, this.controller); - this.targetObserver = new TargetObserver(this, this); - this.outletObserver = new OutletObserver(this, this); - try { - this.controller.initialize(); - this.logDebugActivity("initialize"); - } catch (error2) { - this.handleError(error2, "initializing controller"); + uninstallProgressElement() { + if (this.progressElement.parentNode) { + document.documentElement.removeChild(this.progressElement); } } - connect() { - this.bindingObserver.start(); - this.valueObserver.start(); - this.targetObserver.start(); - this.outletObserver.start(); - try { - this.controller.connect(); - this.logDebugActivity("connect"); - } catch (error2) { - this.handleError(error2, "connecting controller"); + startTrickling() { + if (!this.trickleInterval) { + this.trickleInterval = window.setInterval(this.trickle, ProgressBar.animationDuration); } } + stopTrickling() { + window.clearInterval(this.trickleInterval); + delete this.trickleInterval; + } refresh() { - this.outletObserver.refresh(); + requestAnimationFrame(() => { + this.progressElement.style.width = `${10 + this.value * 90}%`; + }); } - disconnect() { - try { - this.controller.disconnect(); - this.logDebugActivity("disconnect"); - } catch (error2) { - this.handleError(error2, "disconnecting controller"); + createStylesheetElement() { + const element = document.createElement("style"); + element.type = "text/css"; + element.textContent = ProgressBar.defaultCSS; + if (this.cspNonce) { + element.nonce = this.cspNonce; } - this.outletObserver.stop(); - this.targetObserver.stop(); - this.valueObserver.stop(); - this.bindingObserver.stop(); - } - get application() { - return this.module.application; - } - get identifier() { - return this.module.identifier; + return element; } - get schema() { - return this.application.schema; + createProgressElement() { + const element = document.createElement("div"); + element.className = "turbo-progress-bar"; + return element; } - get dispatcher() { - return this.application.dispatcher; + get cspNonce() { + return getMetaContent("csp-nonce"); } - get element() { - return this.scope.element; + }; + ProgressBar.animationDuration = 300; + var HeadSnapshot = class extends Snapshot { + constructor() { + super(...arguments); + this.detailsByOuterHTML = this.children.filter((element) => !elementIsNoscript(element)).map((element) => elementWithoutNonce(element)).reduce((result, element) => { + const { outerHTML } = element; + const details = outerHTML in result ? result[outerHTML] : { + type: elementType(element), + tracked: elementIsTracked(element), + elements: [] + }; + return Object.assign(Object.assign({}, result), { [outerHTML]: Object.assign(Object.assign({}, details), { elements: [...details.elements, element] }) }); + }, {}); } - get parentElement() { - return this.element.parentElement; + get trackedElementSignature() { + return Object.keys(this.detailsByOuterHTML).filter((outerHTML) => this.detailsByOuterHTML[outerHTML].tracked).join(""); } - handleError(error2, message, detail = {}) { - const { identifier, controller, element } = this; - detail = Object.assign({ identifier, controller, element }, detail); - this.application.handleError(error2, `Error ${message}`, detail); + getScriptElementsNotInSnapshot(snapshot) { + return this.getElementsMatchingTypeNotInSnapshot("script", snapshot); } - targetConnected(element, name) { - this.invokeControllerMethod(`${name}TargetConnected`, element); + getStylesheetElementsNotInSnapshot(snapshot) { + return this.getElementsMatchingTypeNotInSnapshot("stylesheet", snapshot); } - targetDisconnected(element, name) { - this.invokeControllerMethod(`${name}TargetDisconnected`, element); + getElementsMatchingTypeNotInSnapshot(matchedType, snapshot) { + return Object.keys(this.detailsByOuterHTML).filter((outerHTML) => !(outerHTML in snapshot.detailsByOuterHTML)).map((outerHTML) => this.detailsByOuterHTML[outerHTML]).filter(({ type }) => type == matchedType).map(({ elements: [element] }) => element); } - outletConnected(outlet, element, name) { - this.invokeControllerMethod(`${namespaceCamelize(name)}OutletConnected`, outlet, element); + get provisionalElements() { + return Object.keys(this.detailsByOuterHTML).reduce((result, outerHTML) => { + const { type, tracked, elements } = this.detailsByOuterHTML[outerHTML]; + if (type == null && !tracked) { + return [...result, ...elements]; + } else if (elements.length > 1) { + return [...result, ...elements.slice(1)]; + } else { + return result; + } + }, []); } - outletDisconnected(outlet, element, name) { - this.invokeControllerMethod(`${namespaceCamelize(name)}OutletDisconnected`, outlet, element); + getMetaValue(name) { + const element = this.findMetaElementByName(name); + return element ? element.getAttribute("content") : null; } - invokeControllerMethod(methodName, ...args) { - const controller = this.controller; - if (typeof controller[methodName] == "function") { - controller[methodName](...args); - } + findMetaElementByName(name) { + return Object.keys(this.detailsByOuterHTML).reduce((result, outerHTML) => { + const { elements: [element] } = this.detailsByOuterHTML[outerHTML]; + return elementIsMetaElementWithName(element, name) ? element : result; + }, void 0); } }; - function bless(constructor) { - return shadow(constructor, getBlessedProperties(constructor)); + function elementType(element) { + if (elementIsScript(element)) { + return "script"; + } else if (elementIsStylesheet(element)) { + return "stylesheet"; + } } - function shadow(constructor, properties) { - const shadowConstructor = extend(constructor); - const shadowProperties = getShadowProperties(constructor.prototype, properties); - Object.defineProperties(shadowConstructor.prototype, shadowProperties); - return shadowConstructor; + function elementIsTracked(element) { + return element.getAttribute("data-turbo-track") == "reload"; } - function getBlessedProperties(constructor) { - const blessings = readInheritableStaticArrayValues(constructor, "blessings"); - return blessings.reduce((blessedProperties, blessing) => { - const properties = blessing(constructor); - for (const key in properties) { - const descriptor = blessedProperties[key] || {}; - blessedProperties[key] = Object.assign(descriptor, properties[key]); - } - return blessedProperties; - }, {}); + function elementIsScript(element) { + const tagName = element.localName; + return tagName == "script"; } - function getShadowProperties(prototype, properties) { - return getOwnKeys(properties).reduce((shadowProperties, key) => { - const descriptor = getShadowedDescriptor(prototype, properties, key); - if (descriptor) { - Object.assign(shadowProperties, { [key]: descriptor }); - } - return shadowProperties; - }, {}); + function elementIsNoscript(element) { + const tagName = element.localName; + return tagName == "noscript"; } - function getShadowedDescriptor(prototype, properties, key) { - const shadowingDescriptor = Object.getOwnPropertyDescriptor(prototype, key); - const shadowedByValue = shadowingDescriptor && "value" in shadowingDescriptor; - if (!shadowedByValue) { - const descriptor = Object.getOwnPropertyDescriptor(properties, key).value; - if (shadowingDescriptor) { - descriptor.get = shadowingDescriptor.get || descriptor.get; - descriptor.set = shadowingDescriptor.set || descriptor.set; - } - return descriptor; - } + function elementIsStylesheet(element) { + const tagName = element.localName; + return tagName == "style" || tagName == "link" && element.getAttribute("rel") == "stylesheet"; } - var getOwnKeys = (() => { - if (typeof Object.getOwnPropertySymbols == "function") { - return (object) => [...Object.getOwnPropertyNames(object), ...Object.getOwnPropertySymbols(object)]; - } else { - return Object.getOwnPropertyNames; - } - })(); - var extend = (() => { - function extendWithReflect(constructor) { - function extended() { - return Reflect.construct(constructor, arguments, new.target); - } - extended.prototype = Object.create(constructor.prototype, { - constructor: { value: extended } - }); - Reflect.setPrototypeOf(extended, constructor); - return extended; - } - function testReflectExtension() { - const a = function() { - this.a.call(this); - }; - const b = extendWithReflect(a); - b.prototype.a = function() { - }; - return new b(); - } - try { - testReflectExtension(); - return extendWithReflect; - } catch (error2) { - return (constructor) => class extended extends constructor { - }; - } - })(); - function blessDefinition(definition) { - return { - identifier: definition.identifier, - controllerConstructor: bless(definition.controllerConstructor) - }; + function elementIsMetaElementWithName(element, name) { + const tagName = element.localName; + return tagName == "meta" && element.getAttribute("name") == name; } - var Module = class { - constructor(application2, definition) { - this.application = application2; - this.definition = blessDefinition(definition); - this.contextsByScope = /* @__PURE__ */ new WeakMap(); - this.connectedContexts = /* @__PURE__ */ new Set(); + function elementWithoutNonce(element) { + if (element.hasAttribute("nonce")) { + element.setAttribute("nonce", ""); } - get identifier() { - return this.definition.identifier; + return element; + } + var PageSnapshot = class extends Snapshot { + static fromHTMLString(html = "") { + return this.fromDocument(parseHTMLDocument(html)); } - get controllerConstructor() { - return this.definition.controllerConstructor; + static fromElement(element) { + return this.fromDocument(element.ownerDocument); } - get contexts() { - return Array.from(this.connectedContexts); + static fromDocument({ head, body }) { + return new this(body, new HeadSnapshot(head)); } - connectContextForScope(scope) { - const context = this.fetchContextForScope(scope); - this.connectedContexts.add(context); - context.connect(); + constructor(element, headSnapshot) { + super(element); + this.headSnapshot = headSnapshot; } - disconnectContextForScope(scope) { - const context = this.contextsByScope.get(scope); - if (context) { - this.connectedContexts.delete(context); - context.disconnect(); + clone() { + const clonedElement = this.element.cloneNode(true); + const selectElements = this.element.querySelectorAll("select"); + const clonedSelectElements = clonedElement.querySelectorAll("select"); + for (const [index, source] of selectElements.entries()) { + const clone = clonedSelectElements[index]; + for (const option of clone.selectedOptions) + option.selected = false; + for (const option of source.selectedOptions) + clone.options[option.index].selected = true; } - } - fetchContextForScope(scope) { - let context = this.contextsByScope.get(scope); - if (!context) { - context = new Context(this, scope); - this.contextsByScope.set(scope, context); + for (const clonedPasswordInput of clonedElement.querySelectorAll('input[type="password"]')) { + clonedPasswordInput.value = ""; } - return context; - } - }; - var ClassMap = class { - constructor(scope) { - this.scope = scope; - } - has(name) { - return this.data.has(this.getDataKey(name)); - } - get(name) { - return this.getAll(name)[0]; - } - getAll(name) { - const tokenString = this.data.get(this.getDataKey(name)) || ""; - return tokenize(tokenString); - } - getAttributeName(name) { - return this.data.getAttributeNameForKey(this.getDataKey(name)); - } - getDataKey(name) { - return `${name}-class`; - } - get data() { - return this.scope.data; - } - }; - var DataMap = class { - constructor(scope) { - this.scope = scope; + return new PageSnapshot(clonedElement, this.headSnapshot); } - get element() { - return this.scope.element; + get headElement() { + return this.headSnapshot.element; } - get identifier() { - return this.scope.identifier; + get rootLocation() { + var _a; + const root = (_a = this.getSetting("root")) !== null && _a !== void 0 ? _a : "/"; + return expandURL(root); } - get(key) { - const name = this.getAttributeNameForKey(key); - return this.element.getAttribute(name); + get cacheControlValue() { + return this.getSetting("cache-control"); } - set(key, value) { - const name = this.getAttributeNameForKey(key); - this.element.setAttribute(name, value); - return this.get(key); + get isPreviewable() { + return this.cacheControlValue != "no-preview"; } - has(key) { - const name = this.getAttributeNameForKey(key); - return this.element.hasAttribute(name); + get isCacheable() { + return this.cacheControlValue != "no-cache"; } - delete(key) { - if (this.has(key)) { - const name = this.getAttributeNameForKey(key); - this.element.removeAttribute(name); - return true; - } else { - return false; - } + get isVisitable() { + return this.getSetting("visit-control") != "reload"; } - getAttributeNameForKey(key) { - return `data-${this.identifier}-${dasherize(key)}`; + getSetting(name) { + return this.headSnapshot.getMetaValue(`turbo-${name}`); } }; - var Guide = class { - constructor(logger) { - this.warnedKeysByObject = /* @__PURE__ */ new WeakMap(); - this.logger = logger; - } - warn(object, key, message) { - let warnedKeys = this.warnedKeysByObject.get(object); - if (!warnedKeys) { - warnedKeys = /* @__PURE__ */ new Set(); - this.warnedKeysByObject.set(object, warnedKeys); - } - if (!warnedKeys.has(key)) { - warnedKeys.add(key); - this.logger.warn(message, object); - } - } + var TimingMetric; + (function(TimingMetric2) { + TimingMetric2["visitStart"] = "visitStart"; + TimingMetric2["requestStart"] = "requestStart"; + TimingMetric2["requestEnd"] = "requestEnd"; + TimingMetric2["visitEnd"] = "visitEnd"; + })(TimingMetric || (TimingMetric = {})); + var VisitState; + (function(VisitState2) { + VisitState2["initialized"] = "initialized"; + VisitState2["started"] = "started"; + VisitState2["canceled"] = "canceled"; + VisitState2["failed"] = "failed"; + VisitState2["completed"] = "completed"; + })(VisitState || (VisitState = {})); + var defaultOptions = { + action: "advance", + historyChanged: false, + visitCachedSnapshot: () => { + }, + willRender: true, + updateHistory: true, + shouldCacheSnapshot: true, + acceptsStreamResponse: false }; - function attributeValueContainsToken(attributeName, token) { - return `[${attributeName}~="${token}"]`; - } - var TargetSet = class { - constructor(scope) { - this.scope = scope; - } - get element() { - return this.scope.element; - } - get identifier() { - return this.scope.identifier; - } - get schema() { - return this.scope.schema; - } - has(targetName) { - return this.find(targetName) != null; - } - find(...targetNames) { - return targetNames.reduce((target, targetName) => target || this.findTarget(targetName) || this.findLegacyTarget(targetName), void 0); + var SystemStatusCode; + (function(SystemStatusCode2) { + SystemStatusCode2[SystemStatusCode2["networkFailure"] = 0] = "networkFailure"; + SystemStatusCode2[SystemStatusCode2["timeoutFailure"] = -1] = "timeoutFailure"; + SystemStatusCode2[SystemStatusCode2["contentTypeMismatch"] = -2] = "contentTypeMismatch"; + })(SystemStatusCode || (SystemStatusCode = {})); + var Visit = class { + constructor(delegate, location2, restorationIdentifier, options = {}) { + this.identifier = uuid(); + this.timingMetrics = {}; + this.followedRedirect = false; + this.historyChanged = false; + this.scrolled = false; + this.shouldCacheSnapshot = true; + this.acceptsStreamResponse = false; + this.snapshotCached = false; + this.state = VisitState.initialized; + this.delegate = delegate; + this.location = location2; + this.restorationIdentifier = restorationIdentifier || uuid(); + const { action, historyChanged, referrer, snapshot, snapshotHTML, response, visitCachedSnapshot, willRender, updateHistory, shouldCacheSnapshot, acceptsStreamResponse } = Object.assign(Object.assign({}, defaultOptions), options); + this.action = action; + this.historyChanged = historyChanged; + this.referrer = referrer; + this.snapshot = snapshot; + this.snapshotHTML = snapshotHTML; + this.response = response; + this.isSamePage = this.delegate.locationWithActionIsSamePage(this.location, this.action); + this.visitCachedSnapshot = visitCachedSnapshot; + this.willRender = willRender; + this.updateHistory = updateHistory; + this.scrolled = !willRender; + this.shouldCacheSnapshot = shouldCacheSnapshot; + this.acceptsStreamResponse = acceptsStreamResponse; } - findAll(...targetNames) { - return targetNames.reduce((targets, targetName) => [ - ...targets, - ...this.findAllTargets(targetName), - ...this.findAllLegacyTargets(targetName) - ], []); + get adapter() { + return this.delegate.adapter; } - findTarget(targetName) { - const selector = this.getSelectorForTargetName(targetName); - return this.scope.findElement(selector); + get view() { + return this.delegate.view; } - findAllTargets(targetName) { - const selector = this.getSelectorForTargetName(targetName); - return this.scope.findAllElements(selector); + get history() { + return this.delegate.history; } - getSelectorForTargetName(targetName) { - const attributeName = this.schema.targetAttributeForScope(this.identifier); - return attributeValueContainsToken(attributeName, targetName); + get restorationData() { + return this.history.getRestorationDataForIdentifier(this.restorationIdentifier); } - findLegacyTarget(targetName) { - const selector = this.getLegacySelectorForTargetName(targetName); - return this.deprecate(this.scope.findElement(selector), targetName); + get silent() { + return this.isSamePage; } - findAllLegacyTargets(targetName) { - const selector = this.getLegacySelectorForTargetName(targetName); - return this.scope.findAllElements(selector).map((element) => this.deprecate(element, targetName)); + start() { + if (this.state == VisitState.initialized) { + this.recordTimingMetric(TimingMetric.visitStart); + this.state = VisitState.started; + this.adapter.visitStarted(this); + this.delegate.visitStarted(this); + } } - getLegacySelectorForTargetName(targetName) { - const targetDescriptor = `${this.identifier}.${targetName}`; - return attributeValueContainsToken(this.schema.targetAttribute, targetDescriptor); + cancel() { + if (this.state == VisitState.started) { + if (this.request) { + this.request.cancel(); + } + this.cancelRender(); + this.state = VisitState.canceled; + } } - deprecate(element, targetName) { - if (element) { - const { identifier } = this; - const attributeName = this.schema.targetAttribute; - const revisedAttributeName = this.schema.targetAttributeForScope(identifier); - this.guide.warn(element, `target:${targetName}`, `Please replace ${attributeName}="${identifier}.${targetName}" with ${revisedAttributeName}="${targetName}". The ${attributeName} attribute is deprecated and will be removed in a future version of Stimulus.`); + complete() { + if (this.state == VisitState.started) { + this.recordTimingMetric(TimingMetric.visitEnd); + this.state = VisitState.completed; + this.followRedirect(); + if (!this.followedRedirect) { + this.adapter.visitCompleted(this); + this.delegate.visitCompleted(this); + } } - return element; } - get guide() { - return this.scope.guide; + fail() { + if (this.state == VisitState.started) { + this.state = VisitState.failed; + this.adapter.visitFailed(this); + } } - }; - var OutletSet = class { - constructor(scope, controllerElement) { - this.scope = scope; - this.controllerElement = controllerElement; + changeHistory() { + var _a; + if (!this.historyChanged && this.updateHistory) { + const actionForHistory = this.location.href === ((_a = this.referrer) === null || _a === void 0 ? void 0 : _a.href) ? "replace" : this.action; + const method = getHistoryMethodForAction(actionForHistory); + this.history.update(method, this.location, this.restorationIdentifier); + this.historyChanged = true; + } } - get element() { - return this.scope.element; + issueRequest() { + if (this.hasPreloadedResponse()) { + this.simulateRequest(); + } else if (this.shouldIssueRequest() && !this.request) { + this.request = new FetchRequest(this, FetchMethod.get, this.location); + this.request.perform(); + } } - get identifier() { - return this.scope.identifier; + simulateRequest() { + if (this.response) { + this.startRequest(); + this.recordResponse(); + this.finishRequest(); + } } - get schema() { - return this.scope.schema; + startRequest() { + this.recordTimingMetric(TimingMetric.requestStart); + this.adapter.visitRequestStarted(this); } - has(outletName) { - return this.find(outletName) != null; + recordResponse(response = this.response) { + this.response = response; + if (response) { + const { statusCode } = response; + if (isSuccessful(statusCode)) { + this.adapter.visitRequestCompleted(this); + } else { + this.adapter.visitRequestFailedWithStatusCode(this, statusCode); + } + } } - find(...outletNames) { - return outletNames.reduce((outlet, outletName) => outlet || this.findOutlet(outletName), void 0); + finishRequest() { + this.recordTimingMetric(TimingMetric.requestEnd); + this.adapter.visitRequestFinished(this); } - findAll(...outletNames) { - return outletNames.reduce((outlets, outletName) => [...outlets, ...this.findAllOutlets(outletName)], []); + loadResponse() { + if (this.response) { + const { statusCode, responseHTML } = this.response; + this.render(async () => { + if (this.shouldCacheSnapshot) + this.cacheSnapshot(); + if (this.view.renderPromise) + await this.view.renderPromise; + if (isSuccessful(statusCode) && responseHTML != null) { + await this.view.renderPage(PageSnapshot.fromHTMLString(responseHTML), false, this.willRender, this); + this.performScroll(); + this.adapter.visitRendered(this); + this.complete(); + } else { + await this.view.renderError(PageSnapshot.fromHTMLString(responseHTML), this); + this.adapter.visitRendered(this); + this.fail(); + } + }); + } } - getSelectorForOutletName(outletName) { - const attributeName = this.schema.outletAttributeForScope(this.identifier, outletName); - return this.controllerElement.getAttribute(attributeName); + getCachedSnapshot() { + const snapshot = this.view.getCachedSnapshotForLocation(this.location) || this.getPreloadedSnapshot(); + if (snapshot && (!getAnchor(this.location) || snapshot.hasAnchor(getAnchor(this.location)))) { + if (this.action == "restore" || snapshot.isPreviewable) { + return snapshot; + } + } } - findOutlet(outletName) { - const selector = this.getSelectorForOutletName(outletName); - if (selector) - return this.findElement(selector, outletName); + getPreloadedSnapshot() { + if (this.snapshotHTML) { + return PageSnapshot.fromHTMLString(this.snapshotHTML); + } } - findAllOutlets(outletName) { - const selector = this.getSelectorForOutletName(outletName); - return selector ? this.findAllElements(selector, outletName) : []; + hasCachedSnapshot() { + return this.getCachedSnapshot() != null; } - findElement(selector, outletName) { - const elements = this.scope.queryElements(selector); - return elements.filter((element) => this.matchesElement(element, selector, outletName))[0]; + loadCachedSnapshot() { + const snapshot = this.getCachedSnapshot(); + if (snapshot) { + const isPreview = this.shouldIssueRequest(); + this.render(async () => { + this.cacheSnapshot(); + if (this.isSamePage) { + this.adapter.visitRendered(this); + } else { + if (this.view.renderPromise) + await this.view.renderPromise; + await this.view.renderPage(snapshot, isPreview, this.willRender, this); + this.performScroll(); + this.adapter.visitRendered(this); + if (!isPreview) { + this.complete(); + } + } + }); + } } - findAllElements(selector, outletName) { - const elements = this.scope.queryElements(selector); - return elements.filter((element) => this.matchesElement(element, selector, outletName)); + followRedirect() { + var _a; + if (this.redirectedToLocation && !this.followedRedirect && ((_a = this.response) === null || _a === void 0 ? void 0 : _a.redirected)) { + this.adapter.visitProposedToLocation(this.redirectedToLocation, { + action: "replace", + response: this.response, + shouldCacheSnapshot: false, + willRender: false + }); + this.followedRedirect = true; + } } - matchesElement(element, selector, outletName) { - const controllerAttribute = element.getAttribute(this.scope.schema.controllerAttribute) || ""; - return element.matches(selector) && controllerAttribute.split(" ").includes(outletName); + goToSamePageAnchor() { + if (this.isSamePage) { + this.render(async () => { + this.cacheSnapshot(); + this.performScroll(); + this.changeHistory(); + this.adapter.visitRendered(this); + }); + } } - }; - var Scope = class { - constructor(schema, element, identifier, logger) { - this.targets = new TargetSet(this); - this.classes = new ClassMap(this); - this.data = new DataMap(this); - this.containsElement = (element2) => { - return element2.closest(this.controllerSelector) === this.element; - }; - this.schema = schema; - this.element = element; - this.identifier = identifier; - this.guide = new Guide(logger); - this.outlets = new OutletSet(this.documentScope, element); + prepareRequest(request) { + if (this.acceptsStreamResponse) { + request.acceptResponseType(StreamMessage.contentType); + } } - findElement(selector) { - return this.element.matches(selector) ? this.element : this.queryElements(selector).find(this.containsElement); + requestStarted() { + this.startRequest(); } - findAllElements(selector) { - return [ - ...this.element.matches(selector) ? [this.element] : [], - ...this.queryElements(selector).filter(this.containsElement) - ]; + requestPreventedHandlingResponse(_request, _response) { } - queryElements(selector) { - return Array.from(this.element.querySelectorAll(selector)); + async requestSucceededWithResponse(request, response) { + const responseHTML = await response.responseHTML; + const { redirected, statusCode } = response; + if (responseHTML == void 0) { + this.recordResponse({ + statusCode: SystemStatusCode.contentTypeMismatch, + redirected + }); + } else { + this.redirectedToLocation = response.redirected ? response.location : void 0; + this.recordResponse({ statusCode, responseHTML, redirected }); + } } - get controllerSelector() { - return attributeValueContainsToken(this.schema.controllerAttribute, this.identifier); + async requestFailedWithResponse(request, response) { + const responseHTML = await response.responseHTML; + const { redirected, statusCode } = response; + if (responseHTML == void 0) { + this.recordResponse({ + statusCode: SystemStatusCode.contentTypeMismatch, + redirected + }); + } else { + this.recordResponse({ statusCode, responseHTML, redirected }); + } } - get isDocumentScope() { - return this.element === document.documentElement; + requestErrored(_request, _error) { + this.recordResponse({ + statusCode: SystemStatusCode.networkFailure, + redirected: false + }); } - get documentScope() { - return this.isDocumentScope ? this : new Scope(this.schema, document.documentElement, this.identifier, this.guide.logger); + requestFinished() { + this.finishRequest(); } - }; - var ScopeObserver = class { - constructor(element, schema, delegate) { - this.element = element; - this.schema = schema; - this.delegate = delegate; - this.valueListObserver = new ValueListObserver(this.element, this.controllerAttribute, this); - this.scopesByIdentifierByElement = /* @__PURE__ */ new WeakMap(); - this.scopeReferenceCounts = /* @__PURE__ */ new WeakMap(); + performScroll() { + if (!this.scrolled && !this.view.forceReloaded) { + if (this.action == "restore") { + this.scrollToRestoredPosition() || this.scrollToAnchor() || this.view.scrollToTop(); + } else { + this.scrollToAnchor() || this.view.scrollToTop(); + } + if (this.isSamePage) { + this.delegate.visitScrolledToSamePageLocation(this.view.lastRenderedLocation, this.location); + } + this.scrolled = true; + } } - start() { - this.valueListObserver.start(); + scrollToRestoredPosition() { + const { scrollPosition } = this.restorationData; + if (scrollPosition) { + this.view.scrollToPosition(scrollPosition); + return true; + } } - stop() { - this.valueListObserver.stop(); + scrollToAnchor() { + const anchor = getAnchor(this.location); + if (anchor != null) { + this.view.scrollToAnchor(anchor); + return true; + } } - get controllerAttribute() { - return this.schema.controllerAttribute; + recordTimingMetric(metric) { + this.timingMetrics[metric] = new Date().getTime(); } - parseValueForToken(token) { - const { element, content: identifier } = token; - const scopesByIdentifier = this.fetchScopesByIdentifierForElement(element); - let scope = scopesByIdentifier.get(identifier); - if (!scope) { - scope = this.delegate.createScopeForElementAndIdentifier(element, identifier); - scopesByIdentifier.set(identifier, scope); + getTimingMetrics() { + return Object.assign({}, this.timingMetrics); + } + getHistoryMethodForAction(action) { + switch (action) { + case "replace": + return history.replaceState; + case "advance": + case "restore": + return history.pushState; } - return scope; } - elementMatchedValue(element, value) { - const referenceCount = (this.scopeReferenceCounts.get(value) || 0) + 1; - this.scopeReferenceCounts.set(value, referenceCount); - if (referenceCount == 1) { - this.delegate.scopeConnected(value); + hasPreloadedResponse() { + return typeof this.response == "object"; + } + shouldIssueRequest() { + if (this.isSamePage) { + return false; + } else if (this.action == "restore") { + return !this.hasCachedSnapshot(); + } else { + return this.willRender; } } - elementUnmatchedValue(element, value) { - const referenceCount = this.scopeReferenceCounts.get(value); - if (referenceCount) { - this.scopeReferenceCounts.set(value, referenceCount - 1); - if (referenceCount == 1) { - this.delegate.scopeDisconnected(value); - } + cacheSnapshot() { + if (!this.snapshotCached) { + this.view.cacheSnapshot(this.snapshot).then((snapshot) => snapshot && this.visitCachedSnapshot(snapshot)); + this.snapshotCached = true; } } - fetchScopesByIdentifierForElement(element) { - let scopesByIdentifier = this.scopesByIdentifierByElement.get(element); - if (!scopesByIdentifier) { - scopesByIdentifier = /* @__PURE__ */ new Map(); - this.scopesByIdentifierByElement.set(element, scopesByIdentifier); + async render(callback) { + this.cancelRender(); + await new Promise((resolve) => { + this.frame = requestAnimationFrame(() => resolve()); + }); + await callback(); + delete this.frame; + } + cancelRender() { + if (this.frame) { + cancelAnimationFrame(this.frame); + delete this.frame; } - return scopesByIdentifier; } }; - var Router = class { - constructor(application2) { - this.application = application2; - this.scopeObserver = new ScopeObserver(this.element, this.schema, this); - this.scopesByIdentifier = new Multimap(); - this.modulesByIdentifier = /* @__PURE__ */ new Map(); + function isSuccessful(statusCode) { + return statusCode >= 200 && statusCode < 300; + } + var BrowserAdapter = class { + constructor(session2) { + this.progressBar = new ProgressBar(); + this.showProgressBar = () => { + this.progressBar.show(); + }; + this.session = session2; } - get element() { - return this.application.element; + visitProposedToLocation(location2, options) { + this.navigator.startVisit(location2, (options === null || options === void 0 ? void 0 : options.restorationIdentifier) || uuid(), options); } - get schema() { - return this.application.schema; + visitStarted(visit2) { + this.location = visit2.location; + visit2.loadCachedSnapshot(); + visit2.issueRequest(); + visit2.goToSamePageAnchor(); } - get logger() { - return this.application.logger; + visitRequestStarted(visit2) { + this.progressBar.setValue(0); + if (visit2.hasCachedSnapshot() || visit2.action != "restore") { + this.showVisitProgressBarAfterDelay(); + } else { + this.showProgressBar(); + } } - get controllerAttribute() { - return this.schema.controllerAttribute; + visitRequestCompleted(visit2) { + visit2.loadResponse(); } - get modules() { - return Array.from(this.modulesByIdentifier.values()); + visitRequestFailedWithStatusCode(visit2, statusCode) { + switch (statusCode) { + case SystemStatusCode.networkFailure: + case SystemStatusCode.timeoutFailure: + case SystemStatusCode.contentTypeMismatch: + return this.reload({ + reason: "request_failed", + context: { + statusCode + } + }); + default: + return visit2.loadResponse(); + } } - get contexts() { - return this.modules.reduce((contexts, module) => contexts.concat(module.contexts), []); + visitRequestFinished(_visit) { + this.progressBar.setValue(1); + this.hideVisitProgressBar(); } - start() { - this.scopeObserver.start(); + visitCompleted(_visit) { } - stop() { - this.scopeObserver.stop(); + pageInvalidated(reason) { + this.reload(reason); } - loadDefinition(definition) { - this.unloadIdentifier(definition.identifier); - const module = new Module(this.application, definition); - this.connectModule(module); - const afterLoad = definition.controllerConstructor.afterLoad; - if (afterLoad) { - afterLoad(definition.identifier, this.application); - } + visitFailed(_visit) { } - unloadIdentifier(identifier) { - const module = this.modulesByIdentifier.get(identifier); - if (module) { - this.disconnectModule(module); - } + visitRendered(_visit) { } - getContextForElementAndIdentifier(element, identifier) { - const module = this.modulesByIdentifier.get(identifier); - if (module) { - return module.contexts.find((context) => context.element == element); - } + formSubmissionStarted(_formSubmission) { + this.progressBar.setValue(0); + this.showFormProgressBarAfterDelay(); } - handleError(error2, message, detail) { - this.application.handleError(error2, message, detail); + formSubmissionFinished(_formSubmission) { + this.progressBar.setValue(1); + this.hideFormProgressBar(); } - createScopeForElementAndIdentifier(element, identifier) { - return new Scope(this.schema, element, identifier, this.logger); + showVisitProgressBarAfterDelay() { + this.visitProgressBarTimeout = window.setTimeout(this.showProgressBar, this.session.progressBarDelay); } - scopeConnected(scope) { - this.scopesByIdentifier.add(scope.identifier, scope); - const module = this.modulesByIdentifier.get(scope.identifier); - if (module) { - module.connectContextForScope(scope); + hideVisitProgressBar() { + this.progressBar.hide(); + if (this.visitProgressBarTimeout != null) { + window.clearTimeout(this.visitProgressBarTimeout); + delete this.visitProgressBarTimeout; } } - scopeDisconnected(scope) { - this.scopesByIdentifier.delete(scope.identifier, scope); - const module = this.modulesByIdentifier.get(scope.identifier); - if (module) { - module.disconnectContextForScope(scope); + showFormProgressBarAfterDelay() { + if (this.formProgressBarTimeout == null) { + this.formProgressBarTimeout = window.setTimeout(this.showProgressBar, this.session.progressBarDelay); } } - connectModule(module) { - this.modulesByIdentifier.set(module.identifier, module); - const scopes = this.scopesByIdentifier.getValuesForKey(module.identifier); - scopes.forEach((scope) => module.connectContextForScope(scope)); + hideFormProgressBar() { + this.progressBar.hide(); + if (this.formProgressBarTimeout != null) { + window.clearTimeout(this.formProgressBarTimeout); + delete this.formProgressBarTimeout; + } } - disconnectModule(module) { - this.modulesByIdentifier.delete(module.identifier); - const scopes = this.scopesByIdentifier.getValuesForKey(module.identifier); - scopes.forEach((scope) => module.disconnectContextForScope(scope)); + reload(reason) { + var _a; + dispatch("turbo:reload", { detail: reason }); + window.location.href = ((_a = this.location) === null || _a === void 0 ? void 0 : _a.toString()) || window.location.href; + } + get navigator() { + return this.session.navigator; } }; - var defaultSchema = { - controllerAttribute: "data-controller", - actionAttribute: "data-action", - targetAttribute: "data-target", - targetAttributeForScope: (identifier) => `data-${identifier}-target`, - outletAttributeForScope: (identifier, outlet) => `data-${identifier}-${outlet}-outlet`, - keyMappings: Object.assign(Object.assign({ enter: "Enter", tab: "Tab", esc: "Escape", space: " ", up: "ArrowUp", down: "ArrowDown", left: "ArrowLeft", right: "ArrowRight", home: "Home", end: "End" }, objectFromEntries("abcdefghijklmnopqrstuvwxyz".split("").map((c) => [c, c]))), objectFromEntries("0123456789".split("").map((n) => [n, n]))) - }; - function objectFromEntries(array) { - return array.reduce((memo, [k, v]) => Object.assign(Object.assign({}, memo), { [k]: v }), {}); - } - var Application = class { - constructor(element = document.documentElement, schema = defaultSchema) { - this.logger = console; - this.debug = false; - this.logDebugActivity = (identifier, functionName, detail = {}) => { - if (this.debug) { - this.logFormattedMessage(identifier, functionName, detail); + var CacheObserver = class { + constructor() { + this.selector = "[data-turbo-temporary]"; + this.deprecatedSelector = "[data-turbo-cache=false]"; + this.started = false; + this.removeTemporaryElements = (_event) => { + for (const element of this.temporaryElements) { + element.remove(); } }; - this.element = element; - this.schema = schema; - this.dispatcher = new Dispatcher(this); - this.router = new Router(this); - this.actionDescriptorFilters = Object.assign({}, defaultActionDescriptorFilters); - } - static start(element, schema) { - const application2 = new this(element, schema); - application2.start(); - return application2; } - async start() { - await domReady(); - this.logDebugActivity("application", "starting"); - this.dispatcher.start(); - this.router.start(); - this.logDebugActivity("application", "start"); + start() { + if (!this.started) { + this.started = true; + addEventListener("turbo:before-cache", this.removeTemporaryElements, false); + } } stop() { - this.logDebugActivity("application", "stopping"); - this.dispatcher.stop(); - this.router.stop(); - this.logDebugActivity("application", "stop"); + if (this.started) { + this.started = false; + removeEventListener("turbo:before-cache", this.removeTemporaryElements, false); + } } - register(identifier, controllerConstructor) { - this.load({ identifier, controllerConstructor }); + get temporaryElements() { + return [...document.querySelectorAll(this.selector), ...this.temporaryElementsWithDeprecation]; } - registerActionOption(name, filter) { - this.actionDescriptorFilters[name] = filter; + get temporaryElementsWithDeprecation() { + const elements = document.querySelectorAll(this.deprecatedSelector); + if (elements.length) { + console.warn(`The ${this.deprecatedSelector} selector is deprecated and will be removed in a future version. Use ${this.selector} instead.`); + } + return [...elements]; } - load(head, ...rest) { - const definitions = Array.isArray(head) ? head : [head, ...rest]; - definitions.forEach((definition) => { - if (definition.controllerConstructor.shouldLoad) { - this.router.loadDefinition(definition); - } - }); + }; + var FrameRedirector = class { + constructor(session2, element) { + this.session = session2; + this.element = element; + this.linkInterceptor = new LinkInterceptor(this, element); + this.formSubmitObserver = new FormSubmitObserver(this, element); } - unload(head, ...rest) { - const identifiers = Array.isArray(head) ? head : [head, ...rest]; - identifiers.forEach((identifier) => this.router.unloadIdentifier(identifier)); + start() { + this.linkInterceptor.start(); + this.formSubmitObserver.start(); } - get controllers() { - return this.router.contexts.map((context) => context.controller); + stop() { + this.linkInterceptor.stop(); + this.formSubmitObserver.stop(); } - getControllerForElementAndIdentifier(element, identifier) { - const context = this.router.getContextForElementAndIdentifier(element, identifier); - return context ? context.controller : null; + shouldInterceptLinkClick(element, _location, _event) { + return this.shouldRedirect(element); } - handleError(error2, message, detail) { - var _a; - this.logger.error(`%s - -%o - -%o`, message, error2, detail); - (_a = window.onerror) === null || _a === void 0 ? void 0 : _a.call(window, message, "", 0, 0, error2); + linkClickIntercepted(element, url, event) { + const frame = this.findFrameElement(element); + if (frame) { + frame.delegate.linkClickIntercepted(element, url, event); + } } - logFormattedMessage(identifier, functionName, detail = {}) { - detail = Object.assign({ application: this }, detail); - this.logger.groupCollapsed(`${identifier} #${functionName}`); - this.logger.log("details:", Object.assign({}, detail)); - this.logger.groupEnd(); + willSubmitForm(element, submitter) { + return element.closest("turbo-frame") == null && this.shouldSubmit(element, submitter) && this.shouldRedirect(element, submitter); } - }; - function domReady() { - return new Promise((resolve) => { - if (document.readyState == "loading") { - document.addEventListener("DOMContentLoaded", () => resolve()); + formSubmitted(element, submitter) { + const frame = this.findFrameElement(element, submitter); + if (frame) { + frame.delegate.formSubmitted(element, submitter); + } + } + shouldSubmit(form, submitter) { + var _a; + const action = getAction(form, submitter); + const meta = this.element.ownerDocument.querySelector(`meta[name="turbo-root"]`); + const rootLocation = expandURL((_a = meta === null || meta === void 0 ? void 0 : meta.content) !== null && _a !== void 0 ? _a : "/"); + return this.shouldRedirect(form, submitter) && locationIsVisitable(action, rootLocation); + } + shouldRedirect(element, submitter) { + const isNavigatable = element instanceof HTMLFormElement ? this.session.submissionIsNavigatable(element, submitter) : this.session.elementIsNavigatable(element); + if (isNavigatable) { + const frame = this.findFrameElement(element, submitter); + return frame ? frame != element.closest("turbo-frame") : false; } else { - resolve(); + return false; } - }); - } - function ClassPropertiesBlessing(constructor) { - const classes = readInheritableStaticArrayValues(constructor, "classes"); - return classes.reduce((properties, classDefinition) => { - return Object.assign(properties, propertiesForClassDefinition(classDefinition)); - }, {}); - } - function propertiesForClassDefinition(key) { - return { - [`${key}Class`]: { - get() { - const { classes } = this; - if (classes.has(key)) { - return classes.get(key); - } else { - const attribute = classes.getAttributeName(key); - throw new Error(`Missing attribute "${attribute}"`); - } - } - }, - [`${key}Classes`]: { - get() { - return this.classes.getAll(key); - } - }, - [`has${capitalize(key)}Class`]: { - get() { - return this.classes.has(key); + } + findFrameElement(element, submitter) { + const id = (submitter === null || submitter === void 0 ? void 0 : submitter.getAttribute("data-turbo-frame")) || element.getAttribute("data-turbo-frame"); + if (id && id != "_top") { + const frame = this.element.querySelector(`#${id}:not([disabled])`); + if (frame instanceof FrameElement) { + return frame; } } - }; - } - function OutletPropertiesBlessing(constructor) { - const outlets = readInheritableStaticArrayValues(constructor, "outlets"); - return outlets.reduce((properties, outletDefinition) => { - return Object.assign(properties, propertiesForOutletDefinition(outletDefinition)); - }, {}); - } - function propertiesForOutletDefinition(name) { - const camelizedName = namespaceCamelize(name); - return { - [`${camelizedName}Outlet`]: { - get() { - const outlet = this.outlets.find(name); - if (outlet) { - const outletController = this.application.getControllerForElementAndIdentifier(outlet, name); - if (outletController) { - return outletController; - } else { - throw new Error(`Missing "data-controller=${name}" attribute on outlet element for "${this.identifier}" controller`); - } - } - throw new Error(`Missing outlet element "${name}" for "${this.identifier}" controller`); - } - }, - [`${camelizedName}Outlets`]: { - get() { - const outlets = this.outlets.findAll(name); - if (outlets.length > 0) { - return outlets.map((outlet) => { - const controller = this.application.getControllerForElementAndIdentifier(outlet, name); - if (controller) { - return controller; - } else { - console.warn(`The provided outlet element is missing the outlet controller "${name}" for "${this.identifier}"`, outlet); - } - }).filter((controller) => controller); - } - return []; - } - }, - [`${camelizedName}OutletElement`]: { - get() { - const outlet = this.outlets.find(name); - if (outlet) { - return outlet; - } else { - throw new Error(`Missing outlet element "${name}" for "${this.identifier}" controller`); + } + }; + var History = class { + constructor(delegate) { + this.restorationIdentifier = uuid(); + this.restorationData = {}; + this.started = false; + this.pageLoaded = false; + this.onPopState = (event) => { + if (this.shouldHandlePopState()) { + const { turbo } = event.state || {}; + if (turbo) { + this.location = new URL(window.location.href); + const { restorationIdentifier } = turbo; + this.restorationIdentifier = restorationIdentifier; + this.delegate.historyPoppedToLocationWithRestorationIdentifier(this.location, restorationIdentifier); } } - }, - [`${camelizedName}OutletElements`]: { - get() { - return this.outlets.findAll(name); - } - }, - [`has${capitalize(camelizedName)}Outlet`]: { - get() { - return this.outlets.has(name); - } + }; + this.onPageLoad = async (_event) => { + await nextMicrotask(); + this.pageLoaded = true; + }; + this.delegate = delegate; + } + start() { + if (!this.started) { + addEventListener("popstate", this.onPopState, false); + addEventListener("load", this.onPageLoad, false); + this.started = true; + this.replace(new URL(window.location.href)); } - }; - } - function TargetPropertiesBlessing(constructor) { - const targets = readInheritableStaticArrayValues(constructor, "targets"); - return targets.reduce((properties, targetDefinition) => { - return Object.assign(properties, propertiesForTargetDefinition(targetDefinition)); - }, {}); - } - function propertiesForTargetDefinition(name) { - return { - [`${name}Target`]: { - get() { - const target = this.targets.find(name); - if (target) { - return target; - } else { - throw new Error(`Missing target element "${name}" for "${this.identifier}" controller`); - } - } - }, - [`${name}Targets`]: { - get() { - return this.targets.findAll(name); - } - }, - [`has${capitalize(name)}Target`]: { - get() { - return this.targets.has(name); - } + } + stop() { + if (this.started) { + removeEventListener("popstate", this.onPopState, false); + removeEventListener("load", this.onPageLoad, false); + this.started = false; } - }; - } - function ValuePropertiesBlessing(constructor) { - const valueDefinitionPairs = readInheritableStaticObjectPairs(constructor, "values"); - const propertyDescriptorMap = { - valueDescriptorMap: { - get() { - return valueDefinitionPairs.reduce((result, valueDefinitionPair) => { - const valueDescriptor = parseValueDefinitionPair(valueDefinitionPair, this.identifier); - const attributeName = this.data.getAttributeNameForKey(valueDescriptor.key); - return Object.assign(result, { [attributeName]: valueDescriptor }); - }, {}); - } + } + push(location2, restorationIdentifier) { + this.update(history.pushState, location2, restorationIdentifier); + } + replace(location2, restorationIdentifier) { + this.update(history.replaceState, location2, restorationIdentifier); + } + update(method, location2, restorationIdentifier = uuid()) { + const state = { turbo: { restorationIdentifier } }; + method.call(history, state, "", location2.href); + this.location = location2; + this.restorationIdentifier = restorationIdentifier; + } + getRestorationDataForIdentifier(restorationIdentifier) { + return this.restorationData[restorationIdentifier] || {}; + } + updateRestorationData(additionalData) { + const { restorationIdentifier } = this; + const restorationData = this.restorationData[restorationIdentifier]; + this.restorationData[restorationIdentifier] = Object.assign(Object.assign({}, restorationData), additionalData); + } + assumeControlOfScrollRestoration() { + var _a; + if (!this.previousScrollRestoration) { + this.previousScrollRestoration = (_a = history.scrollRestoration) !== null && _a !== void 0 ? _a : "auto"; + history.scrollRestoration = "manual"; } - }; - return valueDefinitionPairs.reduce((properties, valueDefinitionPair) => { - return Object.assign(properties, propertiesForValueDefinitionPair(valueDefinitionPair)); - }, propertyDescriptorMap); - } - function propertiesForValueDefinitionPair(valueDefinitionPair, controller) { - const definition = parseValueDefinitionPair(valueDefinitionPair, controller); - const { key, name, reader: read, writer: write } = definition; - return { - [name]: { - get() { - const value = this.data.get(key); - if (value !== null) { - return read(value); - } else { - return definition.defaultValue; - } - }, - set(value) { - if (value === void 0) { - this.data.delete(key); - } else { - this.data.set(key, write(value)); - } - } - }, - [`has${capitalize(name)}`]: { - get() { - return this.data.has(key) || definition.hasCustomDefaultValue; - } + } + relinquishControlOfScrollRestoration() { + if (this.previousScrollRestoration) { + history.scrollRestoration = this.previousScrollRestoration; + delete this.previousScrollRestoration; } - }; - } - function parseValueDefinitionPair([token, typeDefinition], controller) { - return valueDescriptorForTokenAndTypeDefinition({ - controller, - token, - typeDefinition - }); - } - function parseValueTypeConstant(constant) { - switch (constant) { - case Array: - return "array"; - case Boolean: - return "boolean"; - case Number: - return "number"; - case Object: - return "object"; - case String: - return "string"; } - } - function parseValueTypeDefault(defaultValue) { - switch (typeof defaultValue) { - case "boolean": - return "boolean"; - case "number": - return "number"; - case "string": - return "string"; + shouldHandlePopState() { + return this.pageIsLoaded(); } - if (Array.isArray(defaultValue)) - return "array"; - if (Object.prototype.toString.call(defaultValue) === "[object Object]") - return "object"; - } - function parseValueTypeObject(payload) { - const typeFromObject = parseValueTypeConstant(payload.typeObject.type); - if (!typeFromObject) - return; - const defaultValueType = parseValueTypeDefault(payload.typeObject.default); - if (typeFromObject !== defaultValueType) { - const propertyPath = payload.controller ? `${payload.controller}.${payload.token}` : payload.token; - throw new Error(`The specified default value for the Stimulus Value "${propertyPath}" must match the defined type "${typeFromObject}". The provided default value of "${payload.typeObject.default}" is of type "${defaultValueType}".`); - } - return typeFromObject; - } - function parseValueTypeDefinition(payload) { - const typeFromObject = parseValueTypeObject({ - controller: payload.controller, - token: payload.token, - typeObject: payload.typeDefinition - }); - const typeFromDefaultValue = parseValueTypeDefault(payload.typeDefinition); - const typeFromConstant = parseValueTypeConstant(payload.typeDefinition); - const type = typeFromObject || typeFromDefaultValue || typeFromConstant; - if (type) - return type; - const propertyPath = payload.controller ? `${payload.controller}.${payload.typeDefinition}` : payload.token; - throw new Error(`Unknown value type "${propertyPath}" for "${payload.token}" value`); - } - function defaultValueForDefinition(typeDefinition) { - const constant = parseValueTypeConstant(typeDefinition); - if (constant) - return defaultValuesByType[constant]; - const defaultValue = typeDefinition.default; - if (defaultValue !== void 0) - return defaultValue; - return typeDefinition; - } - function valueDescriptorForTokenAndTypeDefinition(payload) { - const key = `${dasherize(payload.token)}-value`; - const type = parseValueTypeDefinition(payload); - return { - type, - key, - name: camelize(key), - get defaultValue() { - return defaultValueForDefinition(payload.typeDefinition); - }, - get hasCustomDefaultValue() { - return parseValueTypeDefault(payload.typeDefinition) !== void 0; - }, - reader: readers[type], - writer: writers[type] || writers.default - }; - } - var defaultValuesByType = { - get array() { - return []; - }, - boolean: false, - number: 0, - get object() { - return {}; - }, - string: "" - }; - var readers = { - array(value) { - const array = JSON.parse(value); - if (!Array.isArray(array)) { - throw new TypeError(`expected value of type "array" but instead got value "${value}" of type "${parseValueTypeDefault(array)}"`); - } - return array; - }, - boolean(value) { - return !(value == "0" || String(value).toLowerCase() == "false"); - }, - number(value) { - return Number(value); - }, - object(value) { - const object = JSON.parse(value); - if (object === null || typeof object != "object" || Array.isArray(object)) { - throw new TypeError(`expected value of type "object" but instead got value "${value}" of type "${parseValueTypeDefault(object)}"`); - } - return object; - }, - string(value) { - return value; + pageIsLoaded() { + return this.pageLoaded || document.readyState == "complete"; } }; - var writers = { - default: writeString, - array: writeJSON, - object: writeJSON - }; - function writeJSON(value) { - return JSON.stringify(value); - } - function writeString(value) { - return `${value}`; - } - var Controller = class { - constructor(context) { - this.context = context; + var Navigator = class { + constructor(delegate) { + this.delegate = delegate; } - static get shouldLoad() { - return true; + proposeVisit(location2, options = {}) { + if (this.delegate.allowsVisitingLocationWithAction(location2, options.action)) { + if (locationIsVisitable(location2, this.view.snapshot.rootLocation)) { + this.delegate.visitProposedToLocation(location2, options); + } else { + window.location.href = location2.toString(); + } + } } - static afterLoad(_identifier, _application) { - return; + startVisit(locatable, restorationIdentifier, options = {}) { + this.stop(); + this.currentVisit = new Visit(this, expandURL(locatable), restorationIdentifier, Object.assign({ referrer: this.location }, options)); + this.currentVisit.start(); } - get application() { - return this.context.application; + submitForm(form, submitter) { + this.stop(); + this.formSubmission = new FormSubmission(this, form, submitter, true); + this.formSubmission.start(); } - get scope() { - return this.context.scope; + stop() { + if (this.formSubmission) { + this.formSubmission.stop(); + delete this.formSubmission; + } + if (this.currentVisit) { + this.currentVisit.cancel(); + delete this.currentVisit; + } } - get element() { - return this.scope.element; + get adapter() { + return this.delegate.adapter; } - get identifier() { - return this.scope.identifier; + get view() { + return this.delegate.view; } - get targets() { - return this.scope.targets; + get history() { + return this.delegate.history; } - get outlets() { - return this.scope.outlets; + formSubmissionStarted(formSubmission) { + if (typeof this.adapter.formSubmissionStarted === "function") { + this.adapter.formSubmissionStarted(formSubmission); + } } - get classes() { - return this.scope.classes; + async formSubmissionSucceededWithResponse(formSubmission, fetchResponse) { + if (formSubmission == this.formSubmission) { + const responseHTML = await fetchResponse.responseHTML; + if (responseHTML) { + const shouldCacheSnapshot = formSubmission.isSafe; + if (!shouldCacheSnapshot) { + this.view.clearSnapshotCache(); + } + const { statusCode, redirected } = fetchResponse; + const action = this.getActionForFormSubmission(formSubmission); + const visitOptions = { + action, + shouldCacheSnapshot, + response: { statusCode, responseHTML, redirected } + }; + this.proposeVisit(fetchResponse.location, visitOptions); + } + } } - get data() { - return this.scope.data; + async formSubmissionFailedWithResponse(formSubmission, fetchResponse) { + const responseHTML = await fetchResponse.responseHTML; + if (responseHTML) { + const snapshot = PageSnapshot.fromHTMLString(responseHTML); + if (fetchResponse.serverError) { + await this.view.renderError(snapshot, this.currentVisit); + } else { + await this.view.renderPage(snapshot, false, true, this.currentVisit); + } + this.view.scrollToTop(); + this.view.clearSnapshotCache(); + } } - initialize() { + formSubmissionErrored(formSubmission, error2) { + console.error(error2); } - connect() { + formSubmissionFinished(formSubmission) { + if (typeof this.adapter.formSubmissionFinished === "function") { + this.adapter.formSubmissionFinished(formSubmission); + } } - disconnect() { + visitStarted(visit2) { + this.delegate.visitStarted(visit2); } - dispatch(eventName, { target = this.element, detail = {}, prefix = this.identifier, bubbles = true, cancelable = true } = {}) { - const type = prefix ? `${prefix}:${eventName}` : eventName; - const event = new CustomEvent(type, { detail, bubbles, cancelable }); - target.dispatchEvent(event); - return event; + visitCompleted(visit2) { + this.delegate.visitCompleted(visit2); } - }; - Controller.blessings = [ - ClassPropertiesBlessing, - TargetPropertiesBlessing, - ValuePropertiesBlessing, - OutletPropertiesBlessing - ]; - Controller.targets = []; - Controller.outlets = []; - Controller.values = {}; - - // app/javascript/controllers/application.js - var application = Application.start(); - application.debug = document.documentElement.classList.contains("debug"); - window.Stimulus = application; - - // app/javascript/controllers/modals/offer_modal_controller.js - var offer_modal_controller_default = class extends Controller { - connect() { - const modal = document.querySelector(`.${this.classNameAttrValue}`); - modal.classList.toggle("is-open"); - document.querySelector(".js-close-modal").addEventListener("click", function() { - modal.classList.toggle("is-open"); - }); + locationWithActionIsSamePage(location2, action) { + const anchor = getAnchor(location2); + const currentAnchor = getAnchor(this.view.lastRenderedLocation); + const isRestorationToTop = action === "restore" && typeof anchor === "undefined"; + return action !== "replace" && getRequestURL(location2) === getRequestURL(this.view.lastRenderedLocation) && (isRestorationToTop || anchor != null && anchor !== currentAnchor); } - }; - __publicField(offer_modal_controller_default, "values", { - classNameAttr: String - }); - - // app/javascript/controllers/modals/modal_controller.js - var modal_controller_default = class extends Controller { - connect() { - console.log("Modal connected"); + visitScrolledToSamePageLocation(oldURL, newURL) { + this.delegate.visitScrolledToSamePageLocation(oldURL, newURL); } - open(event) { - event.preventDefault(); - this.modalTarget.showModal(); - this.modalTarget.addEventListener("click", (e) => this.backdropClick(e)); - console.log("Modal opened"); + get location() { + return this.history.location; } - close(event) { - event.preventDefault(); - this.modalTarget.close(); - console.log("Modal close"); + get restorationIdentifier() { + return this.history.restorationIdentifier; } - backdropClick(event) { - event.target === this.modalTarget && this.close(event); - console.log("Modal close"); + getActionForFormSubmission({ submitter, formElement }) { + return getVisitAction(submitter, formElement) || "advance"; } }; - __publicField(modal_controller_default, "targets", ["modal"]); - - // app/javascript/controllers/form/debounce_controller.js - var debounce_controller_default = class extends Controller { - connect() { - } - search() { - clearTimeout(this.timeout); - this.timeout = setTimeout(() => { - this.formTarget.requestSubmit(); - }, 300); - } - }; - __publicField(debounce_controller_default, "targets", ["form"]); - - // app/javascript/controllers/form/filter_controller.js - var filter_controller_default = class extends Controller { - click(event) { - const label = event.currentTarget; - this.resetAll(); - label.classList.add("is-active"); - } - resetAll() { - this.buttonTargets.forEach((r) => r.checked = false); - this.labelTargets.forEach((l) => l.classList.remove("is-active")); - } - }; - __publicField(filter_controller_default, "targets", ["button", "label"]); - - // app/javascript/controllers/form/autobider_submit_controller.js - var autobider_submit_controller_default = class extends Controller { - connect() { - this.validatingInputPrice(); + var PageStage; + (function(PageStage2) { + PageStage2[PageStage2["initial"] = 0] = "initial"; + PageStage2[PageStage2["loading"] = 1] = "loading"; + PageStage2[PageStage2["interactive"] = 2] = "interactive"; + PageStage2[PageStage2["complete"] = 3] = "complete"; + })(PageStage || (PageStage = {})); + var PageObserver = class { + constructor(delegate) { + this.stage = PageStage.initial; + this.started = false; + this.interpretReadyState = () => { + const { readyState } = this; + if (readyState == "interactive") { + this.pageIsInteractive(); + } else if (readyState == "complete") { + this.pageIsComplete(); + } + }; + this.pageWillUnload = () => { + this.delegate.pageWillUnload(); + }; + this.delegate = delegate; } - disconnect() { - if (this.timeout) { - clearTimeout(this.timeout); + start() { + if (!this.started) { + if (this.stage == PageStage.initial) { + this.stage = PageStage.loading; + } + document.addEventListener("readystatechange", this.interpretReadyState, false); + addEventListener("pagehide", this.pageWillUnload, false); + this.started = true; } } - submitAutobider() { - clearTimeout(this.timeout); - if (parseFloat(this.priceTarget.value) <= 5) { - return; + stop() { + if (this.started) { + document.removeEventListener("readystatechange", this.interpretReadyState, false); + removeEventListener("pagehide", this.pageWillUnload, false); + this.started = false; } - this.timeout = setTimeout(() => { - this.formTarget.requestSubmit(); - }, 300); } - validatePrice(event) { - const char = event.key; - const value = this.priceTarget.value; - if (![".", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "Backspace", "Delete", "Tab", "Enter", "ArrowLeft", "ArrowRight", "ArrowUp", "ArrowDown"].includes(char) || char == "." && value.includes(".")) { - event.preventDefault(); + pageIsInteractive() { + if (this.stage == PageStage.loading) { + this.stage = PageStage.interactive; + this.delegate.pageBecameInteractive(); } } - validatingInputPrice() { - if (parseFloat(this.priceTarget.value) <= 5) { - this.checkboxTarget.disabled = true; - } else { - this.checkboxTarget.disabled = false; + pageIsComplete() { + this.pageIsInteractive(); + if (this.stage == PageStage.interactive) { + this.stage = PageStage.complete; + this.delegate.pageLoaded(); } } - }; - __publicField(autobider_submit_controller_default, "targets", ["form", "price", "checkbox"]); - - // app/javascript/controllers/form/bundle_checkbox_controller.js - var bundle_checkbox_controller_default = class extends Controller { - collect_ids() { - if (this.hasCheckboxesTarget == false) - return; - const regx = /\d+/; - this.hiddenFieldTarget.value = ""; - this.checkboxesTargets.forEach((el) => { - if (el.checked == false) - return; - const element_id = el.id; - this.hiddenFieldTarget.value += ` ${element_id.match(regx)}`; - }); + get readyState() { + return document.readyState; } }; - __publicField(bundle_checkbox_controller_default, "targets", ["hiddenField", "checkboxes"]); - - // app/javascript/controllers/form/checkbox_toggle_controller.js - var checkbox_toggle_controller_default = class extends Controller { - connect() { - this.enableDepositTarget.addEventListener("click", (source) => { - this.disableDepositTarget.checked = false; - }); - this.disableDepositTarget.addEventListener("click", (source) => { - this.enableDepositTarget.checked = false; - }); + var ScrollObserver = class { + constructor(delegate) { + this.started = false; + this.onScroll = () => { + this.updatePosition({ x: window.pageXOffset, y: window.pageYOffset }); + }; + this.delegate = delegate; } - }; - __publicField(checkbox_toggle_controller_default, "targets", ["enableDeposit", "disableDeposit"]); - - // node_modules/@rails/request.js/src/fetch_response.js - var FetchResponse = class { - constructor(response) { - this.response = response; + start() { + if (!this.started) { + addEventListener("scroll", this.onScroll, false); + this.onScroll(); + this.started = true; + } } - get statusCode() { - return this.response.status; + stop() { + if (this.started) { + removeEventListener("scroll", this.onScroll, false); + this.started = false; + } } - get redirected() { - return this.response.redirected; + updatePosition(position) { + this.delegate.scrollPositionChanged(position); } - get ok() { - return this.response.ok; + }; + var StreamMessageRenderer = class { + render({ fragment }) { + Bardo.preservingPermanentElements(this, getPermanentElementMapForFragment(fragment), () => document.documentElement.appendChild(fragment)); } - get unauthenticated() { - return this.statusCode === 401; + enteringBardo(currentPermanentElement, newPermanentElement) { + newPermanentElement.replaceWith(currentPermanentElement.cloneNode(true)); } - get unprocessableEntity() { - return this.statusCode === 422; + leavingBardo() { } - get authenticationURL() { - return this.response.headers.get("WWW-Authenticate"); + }; + function getPermanentElementMapForFragment(fragment) { + const permanentElementsInDocument = queryPermanentElementsAll(document.documentElement); + const permanentElementMap = {}; + for (const permanentElementInDocument of permanentElementsInDocument) { + const { id } = permanentElementInDocument; + for (const streamElement of fragment.querySelectorAll("turbo-stream")) { + const elementInStream = getPermanentElementById(streamElement.templateElement.content, id); + if (elementInStream) { + permanentElementMap[id] = [permanentElementInDocument, elementInStream]; + } + } } - get contentType() { - const contentType = this.response.headers.get("Content-Type") || ""; - return contentType.replace(/;.*$/, ""); + return permanentElementMap; + } + var StreamObserver = class { + constructor(delegate) { + this.sources = /* @__PURE__ */ new Set(); + this.started = false; + this.inspectFetchResponse = (event) => { + const response = fetchResponseFromEvent(event); + if (response && fetchResponseIsStream(response)) { + event.preventDefault(); + this.receiveMessageResponse(response); + } + }; + this.receiveMessageEvent = (event) => { + if (this.started && typeof event.data == "string") { + this.receiveMessageHTML(event.data); + } + }; + this.delegate = delegate; } - get headers() { - return this.response.headers; + start() { + if (!this.started) { + this.started = true; + addEventListener("turbo:before-fetch-response", this.inspectFetchResponse, false); + } } - get html() { - if (this.contentType.match(/^(application|text)\/(html|xhtml\+xml)$/)) { - return this.text; + stop() { + if (this.started) { + this.started = false; + removeEventListener("turbo:before-fetch-response", this.inspectFetchResponse, false); } - return Promise.reject(new Error(`Expected an HTML response but got "${this.contentType}" instead`)); } - get json() { - if (this.contentType.match(/^application\/.*json$/)) { - return this.responseJson || (this.responseJson = this.response.json()); + connectStreamSource(source) { + if (!this.streamSourceIsConnected(source)) { + this.sources.add(source); + source.addEventListener("message", this.receiveMessageEvent, false); } - return Promise.reject(new Error(`Expected a JSON response but got "${this.contentType}" instead`)); } - get text() { - return this.responseText || (this.responseText = this.response.text()); + disconnectStreamSource(source) { + if (this.streamSourceIsConnected(source)) { + this.sources.delete(source); + source.removeEventListener("message", this.receiveMessageEvent, false); + } } - get isTurboStream() { - return this.contentType.match(/^text\/vnd\.turbo-stream\.html/); + streamSourceIsConnected(source) { + return this.sources.has(source); } - async renderTurboStream() { - if (this.isTurboStream) { - if (window.Turbo) { - await window.Turbo.renderStreamMessage(await this.text); - } else { - console.warn("You must set `window.Turbo = Turbo` to automatically process Turbo Stream events with request.js"); - } - } else { - return Promise.reject(new Error(`Expected a Turbo Stream response but got "${this.contentType}" instead`)); + async receiveMessageResponse(response) { + const html = await response.responseHTML; + if (html) { + this.receiveMessageHTML(html); } } - }; - - // node_modules/@rails/request.js/src/request_interceptor.js - var RequestInterceptor = class { - static register(interceptor) { - this.interceptor = interceptor; - } - static get() { - return this.interceptor; - } - static reset() { - this.interceptor = void 0; + receiveMessageHTML(html) { + this.delegate.receivedMessageFromStream(StreamMessage.wrap(html)); } }; - - // node_modules/@rails/request.js/src/lib/utils.js - function getCookie(name) { - const cookies = document.cookie ? document.cookie.split("; ") : []; - const prefix = `${encodeURIComponent(name)}=`; - const cookie = cookies.find((cookie2) => cookie2.startsWith(prefix)); - if (cookie) { - const value = cookie.split("=").slice(1).join("="); - if (value) { - return decodeURIComponent(value); - } - } - } - function compact(object) { - const result = {}; - for (const key in object) { - const value = object[key]; - if (value !== void 0) { - result[key] = value; - } + function fetchResponseFromEvent(event) { + var _a; + const fetchResponse = (_a = event.detail) === null || _a === void 0 ? void 0 : _a.fetchResponse; + if (fetchResponse instanceof FetchResponse) { + return fetchResponse; } - return result; - } - function metaContent(name) { - const element = document.head.querySelector(`meta[name="${name}"]`); - return element && element.content; } - function stringEntriesFromFormData(formData) { - return [...formData].reduce((entries, [name, value]) => { - return entries.concat(typeof value === "string" ? [[name, value]] : []); - }, []); + function fetchResponseIsStream(response) { + var _a; + const contentType = (_a = response.contentType) !== null && _a !== void 0 ? _a : ""; + return contentType.startsWith(StreamMessage.contentType); } - function mergeEntries(searchParams, entries) { - for (const [name, value] of entries) { - if (value instanceof window.File) - continue; - if (searchParams.has(name) && !name.includes("[]")) { - searchParams.delete(name); - searchParams.set(name, value); - } else { - searchParams.append(name, value); - } + var ErrorRenderer = class extends Renderer { + static renderElement(currentElement, newElement) { + const { documentElement, body } = document; + documentElement.replaceChild(newElement, body); } - } - - // node_modules/@rails/request.js/src/fetch_request.js - var FetchRequest = class { - constructor(method, url, options = {}) { - this.method = method; - this.options = options; - this.originalUrl = url.toString(); + async render() { + this.replaceHeadAndBody(); + this.activateScriptElements(); } - async perform() { - try { - const requestInterceptor = RequestInterceptor.get(); - if (requestInterceptor) { - await requestInterceptor(this); + replaceHeadAndBody() { + const { documentElement, head } = document; + documentElement.replaceChild(this.newHead, head); + this.renderElement(this.currentElement, this.newElement); + } + activateScriptElements() { + for (const replaceableElement of this.scriptElements) { + const parentNode = replaceableElement.parentNode; + if (parentNode) { + const element = activateScriptElement(replaceableElement); + parentNode.replaceChild(element, replaceableElement); } - } catch (error2) { - console.error(error2); - } - const response = new FetchResponse(await window.fetch(this.url, this.fetchOptions)); - if (response.unauthenticated && response.authenticationURL) { - return Promise.reject(window.location.href = response.authenticationURL); - } - if (response.ok && response.isTurboStream) { - await response.renderTurboStream(); } - return response; - } - addHeader(key, value) { - const headers = this.additionalHeaders; - headers[key] = value; - this.options.headers = headers; } - sameHostname() { - if (!this.originalUrl.startsWith("http:")) { - return true; - } - try { - return new URL(this.originalUrl).hostname === window.location.hostname; - } catch (_) { - return true; - } + get newHead() { + return this.newSnapshot.headSnapshot.element; } - get fetchOptions() { - return { - method: this.method.toUpperCase(), - headers: this.headers, - body: this.formattedBody, - signal: this.signal, - credentials: "same-origin", - redirect: this.redirect - }; + get scriptElements() { + return document.documentElement.querySelectorAll("script"); } - get headers() { - const baseHeaders = { - "X-Requested-With": "XMLHttpRequest", - "Content-Type": this.contentType, - Accept: this.accept - }; - if (this.sameHostname()) { - baseHeaders["X-CSRF-Token"] = this.csrfToken; + }; + var PageRenderer = class extends Renderer { + static renderElement(currentElement, newElement) { + if (document.body && newElement instanceof HTMLBodyElement) { + document.body.replaceWith(newElement); + } else { + document.documentElement.appendChild(newElement); } - return compact( - Object.assign(baseHeaders, this.additionalHeaders) - ); } - get csrfToken() { - return getCookie(metaContent("csrf-param")) || metaContent("csrf-token"); + get shouldRender() { + return this.newSnapshot.isVisitable && this.trackedElementsAreIdentical; } - get contentType() { - if (this.options.contentType) { - return this.options.contentType; - } else if (this.body == null || this.body instanceof window.FormData) { - return void 0; - } else if (this.body instanceof window.File) { - return this.body.type; + get reloadReason() { + if (!this.newSnapshot.isVisitable) { + return { + reason: "turbo_visit_control_is_reload" + }; } - return "application/json"; - } - get accept() { - switch (this.responseKind) { - case "html": - return "text/html, application/xhtml+xml"; - case "turbo-stream": - return "text/vnd.turbo-stream.html, text/html, application/xhtml+xml"; - case "json": - return "application/json, application/vnd.api+json"; - default: - return "*/*"; + if (!this.trackedElementsAreIdentical) { + return { + reason: "tracked_element_mismatch" + }; } } - get body() { - return this.options.body; + async prepareToRender() { + await this.mergeHead(); } - get query() { - const originalQuery = (this.originalUrl.split("?")[1] || "").split("#")[0]; - const params = new URLSearchParams(originalQuery); - let requestQuery = this.options.query; - if (requestQuery instanceof window.FormData) { - requestQuery = stringEntriesFromFormData(requestQuery); - } else if (requestQuery instanceof window.URLSearchParams) { - requestQuery = requestQuery.entries(); - } else { - requestQuery = Object.entries(requestQuery || {}); + async render() { + if (this.willRender) { + await this.replaceBody(); } - mergeEntries(params, requestQuery); - const query = params.toString(); - return query.length > 0 ? `?${query}` : ""; } - get url() { - return this.originalUrl.split("?")[0].split("#")[0] + this.query; + finishRendering() { + super.finishRendering(); + if (!this.isPreview) { + this.focusFirstAutofocusableElement(); + } } - get responseKind() { - return this.options.responseKind || "html"; + get currentHeadSnapshot() { + return this.currentSnapshot.headSnapshot; } - get signal() { - return this.options.signal; + get newHeadSnapshot() { + return this.newSnapshot.headSnapshot; } - get redirect() { - return this.options.redirect || "follow"; + get newElement() { + return this.newSnapshot.element; } - get additionalHeaders() { - return this.options.headers || {}; + async mergeHead() { + const mergedHeadElements = this.mergeProvisionalElements(); + const newStylesheetElements = this.copyNewHeadStylesheetElements(); + this.copyNewHeadScriptElements(); + await mergedHeadElements; + await newStylesheetElements; } - get formattedBody() { - const bodyIsAString = Object.prototype.toString.call(this.body) === "[object String]"; - const contentTypeIsJson = this.headers["Content-Type"] === "application/json"; - if (contentTypeIsJson && !bodyIsAString) { - return JSON.stringify(this.body); - } - return this.body; + async replaceBody() { + await this.preservingPermanentElements(async () => { + this.activateNewBody(); + await this.assignNewBody(); + }); } - }; - - // app/javascript/controllers/form/checkbox_autosubmit_controller.js - var checkbox_autosubmit_controller_default = class extends Controller { - submit() { - clearTimeout(this.timeout); - this.timeout = setTimeout(() => { - this.performRequest(); - }, 300); + get trackedElementsAreIdentical() { + return this.currentHeadSnapshot.trackedElementSignature == this.newHeadSnapshot.trackedElementSignature; } - disconnect() { - if (this.timeout) { - clearTimeout(this.timeout); + async copyNewHeadStylesheetElements() { + const loadingElements = []; + for (const element of this.newHeadStylesheetElements) { + loadingElements.push(waitForLoad(element)); + document.head.appendChild(element); } + await Promise.all(loadingElements); } - performRequest() { - const originalState = this.checkboxTarget.checked; - const request = new FetchRequest("PATCH", this.urlValue, { - headers: { responseKind: "turbo-stream", accept: "text/vnd.turbo-stream.html" }, - body: new FormData(this.checkboxTarget.form) - }); - const response = request.perform(); - if (!response.ok) { - this.checkboxTarget.checked = !originalState; - console.error("Failed to update user profile", response); + copyNewHeadScriptElements() { + for (const element of this.newHeadScriptElements) { + document.head.appendChild(activateScriptElement(element)); } } - }; - __publicField(checkbox_autosubmit_controller_default, "targets", ["checkbox"]); - __publicField(checkbox_autosubmit_controller_default, "values", { url: String }); - - // app/javascript/controllers/form/autosave_controller.js - var autosave_controller_default = class extends Controller { - connect() { - this.selectValue = this.selectTarget.value; - } - save() { - if (confirm("Are you sure?") == true) { - this.formTarget.requestSubmit(); - } else { - this.selectTarget.value = this.selectValue; + async mergeProvisionalElements() { + const newHeadElements = [...this.newHeadProvisionalElements]; + for (const element of this.currentHeadProvisionalElements) { + if (!this.isCurrentElementInElementList(element, newHeadElements)) { + document.head.removeChild(element); + } + } + for (const element of newHeadElements) { + document.head.appendChild(element); } } - }; - __publicField(autosave_controller_default, "targets", ["form", "select"]); - __publicField(autosave_controller_default, "values", { - select: String - }); - - // app/javascript/controllers/table/ordeable_controller.js - var ordeable_controller_default = class extends Controller { - initialize() { - this.classHandle = this.classHandle.bind(this); + isCurrentElementInElementList(element, elementList) { + for (const [index, newElement] of elementList.entries()) { + if (element.tagName == "TITLE") { + if (newElement.tagName != "TITLE") { + continue; + } + if (element.innerHTML == newElement.innerHTML) { + elementList.splice(index, 1); + return true; + } + } + if (newElement.isEqualNode(element)) { + elementList.splice(index, 1); + return true; + } + } + return false; } - resortTable(_event) { - Turbo.visit("?sort_by=" + this.columnValue + "&sort_direction=" + this.directionValue, { frame: this.frameNameValue }); + removeCurrentHeadProvisionalElements() { + for (const element of this.currentHeadProvisionalElements) { + document.head.removeChild(element); + } } - directionValueChanged() { - this.classHandle(); + copyNewHeadProvisionalElements() { + for (const element of this.newHeadProvisionalElements) { + document.head.appendChild(element); + } } - columnValueChanged() { - this.classHandle(); + activateNewBody() { + document.adoptNode(this.newElement); + this.activateNewBodyScriptElements(); } - classHandle() { - if (this.directionValue == "asc") { - this.thTarget.classList.remove(this.ascClass); - this.thTarget.classList.add(this.descClass); - } else if (this.directionValue == "desc") { - this.thTarget.classList.add(this.ascClass); - this.thTarget.classList.remove(this.descClass); - } else { - this.thTarget.classList.remove(this.ascClass); - this.thTarget.classList.remove(this.descClass); + activateNewBodyScriptElements() { + for (const inertScriptElement of this.newBodyScriptElements) { + const activatedScriptElement = activateScriptElement(inertScriptElement); + inertScriptElement.replaceWith(activatedScriptElement); } } - }; - __publicField(ordeable_controller_default, "values", { direction: String, column: String, frameName: String }); - __publicField(ordeable_controller_default, "targets", ["th"]); - __publicField(ordeable_controller_default, "classes", ["asc", "desc"]); - - // app/javascript/controllers/table/tab_controller.js - var tab_controller_default = class extends Controller { - initialize() { - this.showTab = this.showTab.bind(this); + async assignNewBody() { + await this.renderElement(this.currentElement, this.newElement); } - showTab(event) { - const index = event.params.index; - this.tabTargets.forEach((tab) => { - tab.classList.remove(this.activeClass); - }); - this.contentTargets.forEach((content) => { - content.classList.remove(this.activeClass); - }); - this.tabTargets[index].classList.add(this.activeClass); - this.contentTargets[index].classList.add(this.activeClass); + get newHeadStylesheetElements() { + return this.newHeadSnapshot.getStylesheetElementsNotInSnapshot(this.currentHeadSnapshot); } - }; - __publicField(tab_controller_default, "targets", ["tab", "content"]); - __publicField(tab_controller_default, "classes", ["active"]); - - // app/javascript/controllers/autotax_counter_controller.js - var autotax_counter_controller_default = class extends Controller { - connect() { - this.updateTax(); + get newHeadScriptElements() { + return this.newHeadSnapshot.getScriptElementsNotInSnapshot(this.currentHeadSnapshot); } - count(event) { - const value = parseFloat(event.target.value); - const result = this.resultTarget; - if (!isNaN(value) && value > 0) { - const tax = parseFloat(this.taxValue) || 0; - const taxAmount = value * tax; - const totalAmount = value + taxAmount; - result.innerHTML = this.templateValue.replace("{price}", totalAmount.toFixed(2)).replace("{tax}", (tax * 100).toFixed(2)); - } else { - result.innerHTML = this.defaulttemplateValue; - } + get currentHeadProvisionalElements() { + return this.currentHeadSnapshot.provisionalElements; } - updateTax(event) { - let selectElement = this.element.querySelector("select"); - this.taxValue = selectElement.options[selectElement.selectedIndex].dataset.vatRate || 0; - const priceElement = this.element.querySelector('[name="offer[price]"]'); - this.count({ target: priceElement }); + get newHeadProvisionalElements() { + return this.newHeadSnapshot.provisionalElements; } - }; - __publicField(autotax_counter_controller_default, "targets", ["result"]); - __publicField(autotax_counter_controller_default, "values", { - tax: String, - template: String, - defaulttemplate: String - }); - - // app/javascript/controllers/english_offers_controller.js - var english_offers_controller_default = class extends Controller { - beforeStreamRender(e) { - var content = e.target.templateElement.content; - var currentPrice = content.querySelector(".current_price"); - var auctionRow = content.querySelector(".auctions-table-row"); - if (currentPrice) { - let offerUserId = currentPrice.dataset.userId; - let you = currentPrice.dataset.you; - if (this.values.userId === offerUserId) { - currentPrice.style.color = "green"; - var currentPriceWrapper = document.getElementById("current_price_wrapper"); - currentPriceWrapper.style.color = "green"; - currentPriceWrapper.className = ""; - currentPrice.querySelector(".bidder").textContent = "(" + you + ")"; - } else { - currentPrice.style.color = "red"; - var currentPriceWrapper = document.getElementById("current_price_wrapper"); - currentPriceWrapper.style.color = "red"; - currentPriceWrapper.className = ""; - } - } - if (auctionRow) { - let platform = auctionRow.dataset.platform; - auctionRow.querySelector(".bid_button").textContent = this.values.bidText; - auctionRow.querySelector(".auction_platform").textContent = this.values[platform + "Text"]; - } + get newBodyScriptElements() { + return this.newElement.querySelectorAll("script"); } }; - __publicField(english_offers_controller_default, "values", { - userId: String, - decimalMark: String, - bidText: String, - participateText: String, - englishText: String, - blindText: String - }); - - // app/javascript/controllers/countdown_controller.js - var countdown_controller_default = class extends Controller { - connect() { - if (this.dateValue) { - this.endTime = new Date(this.dateValue).getTime(); - this.update(); - this.timer = setInterval(() => { - this.update(); - }, this.refreshIntervalValue); - } else { - console.log("Missing data-countdown-date-value attribute", this.element); - } + var SnapshotCache = class { + constructor(size) { + this.keys = []; + this.snapshots = {}; + this.size = size; } - disconnect() { - this.stopTimer(); + has(location2) { + return toCacheKey(location2) in this.snapshots; } - stopTimer() { - if (this.timer) { - clearInterval(this.timer); + get(location2) { + if (this.has(location2)) { + const snapshot = this.read(location2); + this.touch(location2); + return snapshot; } } - update() { - let difference = this.timeDifference(); - if (difference < 0) { - var expiredMsg = $("#timer_message").data("expiredMessage"); - $("#timer_message").html(expiredMsg); - this.stopTimer(); - return; - } - let days = Math.floor(difference / (1e3 * 60 * 60 * 24)); - let hours = Math.floor(difference % (1e3 * 60 * 60 * 24) / (1e3 * 60 * 60)); - let minutes = Math.floor(difference % (1e3 * 60 * 60) / (1e3 * 60)); - let seconds = Math.floor(difference % (1e3 * 60) / 1e3); - this.element.innerHTML = this.messageTimerValue.replace("${days}", days).replace("${hours}", hours).replace("${minutes}", minutes).replace("${seconds}", seconds); + put(location2, snapshot) { + this.write(location2, snapshot); + this.touch(location2); + return snapshot; } - timeDifference() { - return this.endTime - new Date().getTime(); + clear() { + this.snapshots = {}; } - }; - __publicField(countdown_controller_default, "values", { - date: String, - refreshInterval: { type: Number, default: 1e3 }, - messageTimer: { type: String, default: "${days}d ${hours}h ${minutes}m ${seconds}s" } - }); - - // app/javascript/controllers/profile_webpush_controller.js - var profile_webpush_controller_default = class extends Controller { - connect() { - console.log("webpush connected!"); - if ("serviceWorker" in navigator && "PushManager" in window) { - navigator.serviceWorker.ready.then( - (registration) => { - registration.pushManager.getSubscription().then( - (subscription) => { - if (subscription) { - this.checkboxTarget.style.disabled = true; - this.checkboxTarget.classList.add("disabled"); - } - } - ); - } - ); - } + read(location2) { + return this.snapshots[toCacheKey(location2)]; } - setupPushNotifications() { - console.log("webpush action!"); - const applicationServerKey2 = this.urlBase64ToUint8Array(this.vapidPublicValue); - navigator.serviceWorker.register("/service-worker.js", { scope: "./" }).then((registration) => { - registration.pushManager.subscribe({ - userVisibleOnly: true, - applicationServerKey: applicationServerKey2 - }).then((subscription) => { - const endpoint = subscription.endpoint; - const p256dh = btoa(String.fromCharCode.apply(null, new Uint8Array(subscription.getKey("p256dh")))); - const auth = btoa(String.fromCharCode.apply(null, new Uint8Array(subscription.getKey("auth")))); - fetch("/push_subscriptions", { - method: "POST", - headers: { - "Content-Type": "application/json", - "X-CSRF-Token": document.querySelector('meta[name="csrf-token"]').getAttribute("content") - }, - body: JSON.stringify({ - subscription: { - endpoint, - p256dh, - auth - } - }) - }); - localStorage.setItem("block-webpush-modal", "true"); - document.querySelector(".webpush-modal").style.display = "none"; - this.checkboxTarget.style.disabled = true; - this.checkboxTarget.classList.add("disabled"); - }); - }); + write(location2, snapshot) { + this.snapshots[toCacheKey(location2)] = snapshot; } - }; - __publicField(profile_webpush_controller_default, "values", { - vapidPublic: String - }); - __publicField(profile_webpush_controller_default, "targets", ["checkbox"]); - - // app/javascript/controllers/push_notification_controller.js - var push_notification_controller_default = class extends Controller { - connect() { - if (!this.userLoginValue) - return; - let subscribed = localStorage.getItem("block-webpush-modal"); - if (subscribed === "true") { - document.querySelector(".webpush-modal").style.display = "none"; - } - if ("serviceWorker" in navigator && "PushManager" in window) { - navigator.serviceWorker.ready.then( - (registration) => { - registration.pushManager.getSubscription().then( - (subscription) => { - if (!subscription) { - if (Notification.permission === "granted") { - this.setupPushNotifications(); - } else { - this.requestPermission(); - } - } - } - ); - } - ); + touch(location2) { + const key = toCacheKey(location2); + const index = this.keys.indexOf(key); + if (index > -1) + this.keys.splice(index, 1); + this.keys.unshift(key); + this.trim(); + } + trim() { + for (const key of this.keys.splice(this.size)) { + delete this.snapshots[key]; } } - requestPermission() { - window.addEventListener("load", () => { - Notification.requestPermission().then((permission) => { - if (permission === "granted") { - this.setupPushNotifications(applicationServerKey); - } - }); - }); + }; + var PageView = class extends View { + constructor() { + super(...arguments); + this.snapshotCache = new SnapshotCache(10); + this.lastRenderedLocation = new URL(location.href); + this.forceReloaded = false; } - setupPushNotifications() { - const applicationServerKey2 = this.urlBase64ToUint8Array(this.vapidPublicValue); - console.log(this.vapidPublicValue); - navigator.serviceWorker.register("/service-worker.js", { scope: "./" }).then((registration) => { - console.log("Service Worker registered successfully:", registration); - registration.pushManager.subscribe({ - userVisibleOnly: true, - applicationServerKey: applicationServerKey2 - }).then((subscription) => { - const endpoint = subscription.endpoint; - const p256dh = btoa(String.fromCharCode.apply(null, new Uint8Array(subscription.getKey("p256dh")))); - const auth = btoa(String.fromCharCode.apply(null, new Uint8Array(subscription.getKey("auth")))); - fetch("/push_subscriptions", { - method: "POST", - headers: { - "Content-Type": "application/json", - "X-CSRF-Token": document.querySelector('meta[name="csrf-token"]').getAttribute("content") - }, - body: JSON.stringify({ - subscription: { - endpoint, - p256dh, - auth - } - }) - }); - localStorage.setItem("block-webpush-modal", "true"); - document.querySelector(".webpush-modal").style.display = "none"; - }); - }).catch((err) => { - console.log("Service Worker registration failed:", err); - }); - ; + renderPage(snapshot, isPreview = false, willRender = true, visit2) { + const renderer = new PageRenderer(this.snapshot, snapshot, PageRenderer.renderElement, isPreview, willRender); + if (!renderer.shouldRender) { + this.forceReloaded = true; + } else { + visit2 === null || visit2 === void 0 ? void 0 : visit2.changeHistory(); + } + return this.render(renderer); } - close() { - document.querySelector(".webpush-modal").style.display = "none"; + renderError(snapshot, visit2) { + visit2 === null || visit2 === void 0 ? void 0 : visit2.changeHistory(); + const renderer = new ErrorRenderer(this.snapshot, snapshot, ErrorRenderer.renderElement, false); + return this.render(renderer); } - decline() { - localStorage.setItem("block-webpush-modal", "true"); - document.querySelector(".webpush-modal").style.display = "none"; + clearSnapshotCache() { + this.snapshotCache.clear(); } - urlBase64ToUint8Array(base64String) { - var padding = "=".repeat((4 - base64String.length % 4) % 4); - var base64 = (base64String + padding).replace(/\-/g, "+").replace(/_/g, "/"); - var rawData = window.atob(base64); - var outputArray = new Uint8Array(rawData.length); - for (var i = 0; i < rawData.length; ++i) { - outputArray[i] = rawData.charCodeAt(i); + async cacheSnapshot(snapshot = this.snapshot) { + if (snapshot.isCacheable) { + this.delegate.viewWillCacheSnapshot(); + const { lastRenderedLocation: location2 } = this; + await nextEventLoopTick(); + const cachedSnapshot = snapshot.clone(); + this.snapshotCache.put(location2, cachedSnapshot); + return cachedSnapshot; } - return outputArray; + } + getCachedSnapshotForLocation(location2) { + return this.snapshotCache.get(location2); + } + get snapshot() { + return PageSnapshot.fromElement(this.element); } }; - __publicField(push_notification_controller_default, "values", { - vapidPublic: String, - userLogin: Boolean - }); - - // app/javascript/controllers/index.js - application.register("modals--offer-modal", offer_modal_controller_default); - application.register("modals--modal", modal_controller_default); - application.register("form--debounce", debounce_controller_default); - application.register("form--filter", filter_controller_default); - application.register("form--autobider-submit", autobider_submit_controller_default); - application.register("form--bundle-checkbox", bundle_checkbox_controller_default); - application.register("form--checkbox-toggle", checkbox_toggle_controller_default); - application.register("form--checkbox-autosubmit", checkbox_autosubmit_controller_default); - application.register("form--autosave", autosave_controller_default); - application.register("table--ordeable", ordeable_controller_default); - application.register("table--tab", tab_controller_default); - application.register("autotax-counter", autotax_counter_controller_default); - application.register("english-offer", english_offers_controller_default); - application.register("countdown", countdown_controller_default); - application.register("profile-webpush", profile_webpush_controller_default); - application.register("push-notification", push_notification_controller_default); - - // node_modules/@hotwired/turbo/dist/turbo.es2017-esm.js - (function() { - if (window.Reflect === void 0 || window.customElements === void 0 || window.customElements.polyfillWrapFlushCallback) { - return; + var Preloader = class { + constructor(delegate) { + this.selector = "a[data-turbo-preload]"; + this.delegate = delegate; } - const BuiltInHTMLElement = HTMLElement; - const wrapperForTheName = { - HTMLElement: function HTMLElement2() { - return Reflect.construct(BuiltInHTMLElement, [], this.constructor); - } - }; - window.HTMLElement = wrapperForTheName["HTMLElement"]; - HTMLElement.prototype = BuiltInHTMLElement.prototype; - HTMLElement.prototype.constructor = HTMLElement; - Object.setPrototypeOf(HTMLElement, BuiltInHTMLElement); - })(); - (function(prototype) { - if (typeof prototype.requestSubmit == "function") - return; - prototype.requestSubmit = function(submitter) { - if (submitter) { - validateSubmitter(submitter, this); - submitter.click(); + get snapshotCache() { + return this.delegate.navigator.view.snapshotCache; + } + start() { + if (document.readyState === "loading") { + return document.addEventListener("DOMContentLoaded", () => { + this.preloadOnLoadLinksForView(document.body); + }); } else { - submitter = document.createElement("input"); - submitter.type = "submit"; - submitter.hidden = true; - this.appendChild(submitter); - submitter.click(); - this.removeChild(submitter); + this.preloadOnLoadLinksForView(document.body); } - }; - function validateSubmitter(submitter, form) { - submitter instanceof HTMLElement || raise(TypeError, "parameter 1 is not of type 'HTMLElement'"); - submitter.type == "submit" || raise(TypeError, "The specified element is not a submit button"); - submitter.form == form || raise(DOMException, "The specified element is not owned by this form element", "NotFoundError"); } - function raise(errorConstructor, message, name) { - throw new errorConstructor("Failed to execute 'requestSubmit' on 'HTMLFormElement': " + message + ".", name); + preloadOnLoadLinksForView(element) { + for (const link of element.querySelectorAll(this.selector)) { + this.preloadURL(link); + } } - })(HTMLFormElement.prototype); - var submittersByForm = /* @__PURE__ */ new WeakMap(); - function findSubmitterFromClickTarget(target) { - const element = target instanceof Element ? target : target instanceof Node ? target.parentElement : null; - const candidate = element ? element.closest("input, button") : null; - return (candidate === null || candidate === void 0 ? void 0 : candidate.type) == "submit" ? candidate : null; - } - function clickCaptured(event) { - const submitter = findSubmitterFromClickTarget(event.target); - if (submitter && submitter.form) { - submittersByForm.set(submitter.form, submitter); - } - } - (function() { - if ("submitter" in Event.prototype) - return; - let prototype = window.Event.prototype; - if ("SubmitEvent" in window && /Apple Computer/.test(navigator.vendor)) { - prototype = window.SubmitEvent.prototype; - } else if ("SubmitEvent" in window) { - return; - } - addEventListener("click", clickCaptured, true); - Object.defineProperty(prototype, "submitter", { - get() { - if (this.type == "submit" && this.target instanceof HTMLFormElement) { - return submittersByForm.get(this.target); - } + async preloadURL(link) { + const location2 = new URL(link.href); + if (this.snapshotCache.has(location2)) { + return; + } + try { + const response = await fetch(location2.toString(), { headers: { "VND.PREFETCH": "true", Accept: "text/html" } }); + const responseText = await response.text(); + const snapshot = PageSnapshot.fromHTMLString(responseText); + this.snapshotCache.put(location2, snapshot); + } catch (_) { } - }); - })(); - var FrameLoadingStyle; - (function(FrameLoadingStyle2) { - FrameLoadingStyle2["eager"] = "eager"; - FrameLoadingStyle2["lazy"] = "lazy"; - })(FrameLoadingStyle || (FrameLoadingStyle = {})); - var FrameElement = class extends HTMLElement { - static get observedAttributes() { - return ["disabled", "complete", "loading", "src"]; } + }; + var Session = class { constructor() { - super(); - this.loaded = Promise.resolve(); - this.delegate = new FrameElement.delegateConstructor(this); - } - connectedCallback() { - this.delegate.connect(); + this.navigator = new Navigator(this); + this.history = new History(this); + this.preloader = new Preloader(this); + this.view = new PageView(this, document.documentElement); + this.adapter = new BrowserAdapter(this); + this.pageObserver = new PageObserver(this); + this.cacheObserver = new CacheObserver(); + this.linkClickObserver = new LinkClickObserver(this, window); + this.formSubmitObserver = new FormSubmitObserver(this, document); + this.scrollObserver = new ScrollObserver(this); + this.streamObserver = new StreamObserver(this); + this.formLinkClickObserver = new FormLinkClickObserver(this, document.documentElement); + this.frameRedirector = new FrameRedirector(this, document.documentElement); + this.streamMessageRenderer = new StreamMessageRenderer(); + this.drive = true; + this.enabled = true; + this.progressBarDelay = 500; + this.started = false; + this.formMode = "on"; } - disconnectedCallback() { - this.delegate.disconnect(); + start() { + if (!this.started) { + this.pageObserver.start(); + this.cacheObserver.start(); + this.formLinkClickObserver.start(); + this.linkClickObserver.start(); + this.formSubmitObserver.start(); + this.scrollObserver.start(); + this.streamObserver.start(); + this.frameRedirector.start(); + this.history.start(); + this.preloader.start(); + this.started = true; + this.enabled = true; + } } - reload() { - return this.delegate.sourceURLReloaded(); + disable() { + this.enabled = false; } - attributeChangedCallback(name) { - if (name == "loading") { - this.delegate.loadingStyleChanged(); - } else if (name == "complete") { - this.delegate.completeChanged(); - } else if (name == "src") { - this.delegate.sourceURLChanged(); - } else { - this.delegate.disabledChanged(); + stop() { + if (this.started) { + this.pageObserver.stop(); + this.cacheObserver.stop(); + this.formLinkClickObserver.stop(); + this.linkClickObserver.stop(); + this.formSubmitObserver.stop(); + this.scrollObserver.stop(); + this.streamObserver.stop(); + this.frameRedirector.stop(); + this.history.stop(); + this.started = false; } } - get src() { - return this.getAttribute("src"); + registerAdapter(adapter) { + this.adapter = adapter; } - set src(value) { - if (value) { - this.setAttribute("src", value); + visit(location2, options = {}) { + const frameElement = options.frame ? document.getElementById(options.frame) : null; + if (frameElement instanceof FrameElement) { + frameElement.src = location2.toString(); + frameElement.loaded; } else { - this.removeAttribute("src"); + this.navigator.proposeVisit(expandURL(location2), options); } } - get loading() { - return frameLoadingStyleFromString(this.getAttribute("loading") || ""); + connectStreamSource(source) { + this.streamObserver.connectStreamSource(source); } - set loading(value) { - if (value) { - this.setAttribute("loading", value); - } else { - this.removeAttribute("loading"); - } + disconnectStreamSource(source) { + this.streamObserver.disconnectStreamSource(source); } - get disabled() { - return this.hasAttribute("disabled"); + renderStreamMessage(message) { + this.streamMessageRenderer.render(StreamMessage.wrap(message)); } - set disabled(value) { - if (value) { - this.setAttribute("disabled", ""); + clearCache() { + this.view.clearSnapshotCache(); + } + setProgressBarDelay(delay) { + this.progressBarDelay = delay; + } + setFormMode(mode) { + this.formMode = mode; + } + get location() { + return this.history.location; + } + get restorationIdentifier() { + return this.history.restorationIdentifier; + } + historyPoppedToLocationWithRestorationIdentifier(location2, restorationIdentifier) { + if (this.enabled) { + this.navigator.startVisit(location2, restorationIdentifier, { + action: "restore", + historyChanged: true + }); } else { - this.removeAttribute("disabled"); + this.adapter.pageInvalidated({ + reason: "turbo_disabled" + }); } } - get autoscroll() { - return this.hasAttribute("autoscroll"); + scrollPositionChanged(position) { + this.history.updateRestorationData({ scrollPosition: position }); } - set autoscroll(value) { - if (value) { - this.setAttribute("autoscroll", ""); - } else { - this.removeAttribute("autoscroll"); + willSubmitFormLinkToLocation(link, location2) { + return this.elementIsNavigatable(link) && locationIsVisitable(location2, this.snapshot.rootLocation); + } + submittedFormLinkToLocation() { + } + willFollowLinkToLocation(link, location2, event) { + return this.elementIsNavigatable(link) && locationIsVisitable(location2, this.snapshot.rootLocation) && this.applicationAllowsFollowingLinkToLocation(link, location2, event); + } + followedLinkToLocation(link, location2) { + const action = this.getActionForLink(link); + const acceptsStreamResponse = link.hasAttribute("data-turbo-stream"); + this.visit(location2.href, { action, acceptsStreamResponse }); + } + allowsVisitingLocationWithAction(location2, action) { + return this.locationWithActionIsSamePage(location2, action) || this.applicationAllowsVisitingLocation(location2); + } + visitProposedToLocation(location2, options) { + extendURLWithDeprecatedProperties(location2); + this.adapter.visitProposedToLocation(location2, options); + } + visitStarted(visit2) { + if (!visit2.acceptsStreamResponse) { + markAsBusy(document.documentElement); + } + extendURLWithDeprecatedProperties(visit2.location); + if (!visit2.silent) { + this.notifyApplicationAfterVisitingLocation(visit2.location, visit2.action); } } - get complete() { - return !this.delegate.isLoading; + visitCompleted(visit2) { + clearBusyState(document.documentElement); + this.notifyApplicationAfterPageLoad(visit2.getTimingMetrics()); } - get isActive() { - return this.ownerDocument === document && !this.isPreview; + locationWithActionIsSamePage(location2, action) { + return this.navigator.locationWithActionIsSamePage(location2, action); } - get isPreview() { - var _a, _b; - return (_b = (_a = this.ownerDocument) === null || _a === void 0 ? void 0 : _a.documentElement) === null || _b === void 0 ? void 0 : _b.hasAttribute("data-turbo-preview"); + visitScrolledToSamePageLocation(oldURL, newURL) { + this.notifyApplicationAfterVisitingSamePageLocation(oldURL, newURL); } - }; - function frameLoadingStyleFromString(style) { - switch (style.toLowerCase()) { - case "lazy": - return FrameLoadingStyle.lazy; - default: - return FrameLoadingStyle.eager; + willSubmitForm(form, submitter) { + const action = getAction(form, submitter); + return this.submissionIsNavigatable(form, submitter) && locationIsVisitable(expandURL(action), this.snapshot.rootLocation); } - } - function expandURL(locatable) { - return new URL(locatable.toString(), document.baseURI); - } - function getAnchor(url) { - let anchorMatch; - if (url.hash) { - return url.hash.slice(1); - } else if (anchorMatch = url.href.match(/#(.*)$/)) { - return anchorMatch[1]; + formSubmitted(form, submitter) { + this.navigator.submitForm(form, submitter); } - } - function getAction(form, submitter) { - const action = (submitter === null || submitter === void 0 ? void 0 : submitter.getAttribute("formaction")) || form.getAttribute("action") || form.action; - return expandURL(action); - } - function getExtension(url) { - return (getLastPathComponent(url).match(/\.[^.]*$/) || [])[0] || ""; - } - function isHTML(url) { - return !!getExtension(url).match(/^(?:|\.(?:htm|html|xhtml|php))$/); - } - function isPrefixedBy(baseURL, url) { - const prefix = getPrefix(url); - return baseURL.href === expandURL(prefix).href || baseURL.href.startsWith(prefix); - } - function locationIsVisitable(location2, rootLocation) { - return isPrefixedBy(location2, rootLocation) && isHTML(location2); - } - function getRequestURL(url) { - const anchor = getAnchor(url); - return anchor != null ? url.href.slice(0, -(anchor.length + 1)) : url.href; - } - function toCacheKey(url) { - return getRequestURL(url); - } - function urlsAreEqual(left, right) { - return expandURL(left).href == expandURL(right).href; - } - function getPathComponents(url) { - return url.pathname.split("/").slice(1); - } - function getLastPathComponent(url) { - return getPathComponents(url).slice(-1)[0]; - } - function getPrefix(url) { - return addTrailingSlash(url.origin + url.pathname); - } - function addTrailingSlash(value) { - return value.endsWith("/") ? value : value + "/"; - } - var FetchResponse2 = class { - constructor(response) { - this.response = response; + pageBecameInteractive() { + this.view.lastRenderedLocation = this.location; + this.notifyApplicationAfterPageLoad(); } - get succeeded() { - return this.response.ok; + pageLoaded() { + this.history.assumeControlOfScrollRestoration(); } - get failed() { - return !this.succeeded; + pageWillUnload() { + this.history.relinquishControlOfScrollRestoration(); } - get clientError() { - return this.statusCode >= 400 && this.statusCode <= 499; + receivedMessageFromStream(message) { + this.renderStreamMessage(message); } - get serverError() { - return this.statusCode >= 500 && this.statusCode <= 599; + viewWillCacheSnapshot() { + var _a; + if (!((_a = this.navigator.currentVisit) === null || _a === void 0 ? void 0 : _a.silent)) { + this.notifyApplicationBeforeCachingSnapshot(); + } } - get redirected() { - return this.response.redirected; + allowsImmediateRender({ element }, options) { + const event = this.notifyApplicationBeforeRender(element, options); + const { defaultPrevented, detail: { render } } = event; + if (this.view.renderer && render) { + this.view.renderer.renderElement = render; + } + return !defaultPrevented; } - get location() { - return expandURL(this.response.url); + viewRenderedSnapshot(_snapshot, _isPreview) { + this.view.lastRenderedLocation = this.history.location; + this.notifyApplicationAfterRender(); } - get isHTML() { - return this.contentType && this.contentType.match(/^(?:text\/([^\s;,]+\b)?html|application\/xhtml\+xml)\b/); + preloadOnLoadLinksForView(element) { + this.preloader.preloadOnLoadLinksForView(element); } - get statusCode() { - return this.response.status; + viewInvalidated(reason) { + this.adapter.pageInvalidated(reason); } - get contentType() { - return this.header("Content-Type"); + frameLoaded(frame) { + this.notifyApplicationAfterFrameLoad(frame); } - get responseText() { - return this.response.clone().text(); + frameRendered(fetchResponse, frame) { + this.notifyApplicationAfterFrameRender(fetchResponse, frame); } - get responseHTML() { - if (this.isHTML) { - return this.response.clone().text(); - } else { - return Promise.resolve(void 0); - } + applicationAllowsFollowingLinkToLocation(link, location2, ev) { + const event = this.notifyApplicationAfterClickingLinkToLocation(link, location2, ev); + return !event.defaultPrevented; } - header(name) { - return this.response.headers.get(name); + applicationAllowsVisitingLocation(location2) { + const event = this.notifyApplicationBeforeVisitingLocation(location2); + return !event.defaultPrevented; } - }; - function activateScriptElement(element) { - if (element.getAttribute("data-turbo-eval") == "false") { - return element; - } else { - const createdScriptElement = document.createElement("script"); - const cspNonce = getMetaContent("csp-nonce"); - if (cspNonce) { - createdScriptElement.nonce = cspNonce; - } - createdScriptElement.textContent = element.textContent; - createdScriptElement.async = false; - copyElementAttributes(createdScriptElement, element); - return createdScriptElement; + notifyApplicationAfterClickingLinkToLocation(link, location2, event) { + return dispatch("turbo:click", { + target: link, + detail: { url: location2.href, originalEvent: event }, + cancelable: true + }); } - } - function copyElementAttributes(destinationElement, sourceElement) { - for (const { name, value } of sourceElement.attributes) { - destinationElement.setAttribute(name, value); + notifyApplicationBeforeVisitingLocation(location2) { + return dispatch("turbo:before-visit", { + detail: { url: location2.href }, + cancelable: true + }); } - } - function createDocumentFragment(html) { - const template = document.createElement("template"); - template.innerHTML = html; - return template.content; - } - function dispatch(eventName, { target, cancelable, detail } = {}) { - const event = new CustomEvent(eventName, { - cancelable, - bubbles: true, - composed: true, - detail - }); - if (target && target.isConnected) { - target.dispatchEvent(event); - } else { - document.documentElement.dispatchEvent(event); + notifyApplicationAfterVisitingLocation(location2, action) { + return dispatch("turbo:visit", { detail: { url: location2.href, action } }); } - return event; - } - function nextAnimationFrame() { - return new Promise((resolve) => requestAnimationFrame(() => resolve())); - } - function nextEventLoopTick() { - return new Promise((resolve) => setTimeout(() => resolve(), 0)); - } - function nextMicrotask() { - return Promise.resolve(); - } - function parseHTMLDocument(html = "") { - return new DOMParser().parseFromString(html, "text/html"); - } - function unindent(strings, ...values) { - const lines = interpolate(strings, values).replace(/^\n/, "").split("\n"); - const match = lines[0].match(/^\s+/); - const indent = match ? match[0].length : 0; - return lines.map((line) => line.slice(indent)).join("\n"); - } - function interpolate(strings, values) { - return strings.reduce((result, string, i) => { - const value = values[i] == void 0 ? "" : values[i]; - return result + string + value; - }, ""); - } - function uuid() { - return Array.from({ length: 36 }).map((_, i) => { - if (i == 8 || i == 13 || i == 18 || i == 23) { - return "-"; - } else if (i == 14) { - return "4"; - } else if (i == 19) { - return (Math.floor(Math.random() * 4) + 8).toString(16); + notifyApplicationBeforeCachingSnapshot() { + return dispatch("turbo:before-cache"); + } + notifyApplicationBeforeRender(newBody, options) { + return dispatch("turbo:before-render", { + detail: Object.assign({ newBody }, options), + cancelable: true + }); + } + notifyApplicationAfterRender() { + return dispatch("turbo:render"); + } + notifyApplicationAfterPageLoad(timing = {}) { + return dispatch("turbo:load", { + detail: { url: this.location.href, timing } + }); + } + notifyApplicationAfterVisitingSamePageLocation(oldURL, newURL) { + dispatchEvent(new HashChangeEvent("hashchange", { + oldURL: oldURL.toString(), + newURL: newURL.toString() + })); + } + notifyApplicationAfterFrameLoad(frame) { + return dispatch("turbo:frame-load", { target: frame }); + } + notifyApplicationAfterFrameRender(fetchResponse, frame) { + return dispatch("turbo:frame-render", { + detail: { fetchResponse }, + target: frame, + cancelable: true + }); + } + submissionIsNavigatable(form, submitter) { + if (this.formMode == "off") { + return false; } else { - return Math.floor(Math.random() * 15).toString(16); + const submitterIsNavigatable = submitter ? this.elementIsNavigatable(submitter) : true; + if (this.formMode == "optin") { + return submitterIsNavigatable && form.closest('[data-turbo="true"]') != null; + } else { + return submitterIsNavigatable && this.elementIsNavigatable(form); + } } - }).join(""); - } - function getAttribute(attributeName, ...elements) { - for (const value of elements.map((element) => element === null || element === void 0 ? void 0 : element.getAttribute(attributeName))) { - if (typeof value == "string") - return value; } - return null; - } - function hasAttribute(attributeName, ...elements) { - return elements.some((element) => element && element.hasAttribute(attributeName)); - } - function markAsBusy(...elements) { - for (const element of elements) { - if (element.localName == "turbo-frame") { - element.setAttribute("busy", ""); + elementIsNavigatable(element) { + const container = findClosestRecursively(element, "[data-turbo]"); + const withinFrame = findClosestRecursively(element, "turbo-frame"); + if (this.drive || withinFrame) { + if (container) { + return container.getAttribute("data-turbo") != "false"; + } else { + return true; + } + } else { + if (container) { + return container.getAttribute("data-turbo") == "true"; + } else { + return false; + } } - element.setAttribute("aria-busy", "true"); } - } - function clearBusyState(...elements) { - for (const element of elements) { - if (element.localName == "turbo-frame") { - element.removeAttribute("busy"); + getActionForLink(link) { + return getVisitAction(link) || "advance"; + } + get snapshot() { + return this.view.snapshot; + } + }; + function extendURLWithDeprecatedProperties(url) { + Object.defineProperties(url, deprecatedLocationPropertyDescriptors); + } + var deprecatedLocationPropertyDescriptors = { + absoluteURL: { + get() { + return this.toString(); } - element.removeAttribute("aria-busy"); } + }; + var Cache = class { + constructor(session2) { + this.session = session2; + } + clear() { + this.session.clearCache(); + } + resetCacheControl() { + this.setCacheControl(""); + } + exemptPageFromCache() { + this.setCacheControl("no-cache"); + } + exemptPageFromPreview() { + this.setCacheControl("no-preview"); + } + setCacheControl(value) { + setMetaContent("turbo-cache-control", value); + } + }; + var StreamActions = { + after() { + this.targetElements.forEach((e) => { + var _a; + return (_a = e.parentElement) === null || _a === void 0 ? void 0 : _a.insertBefore(this.templateContent, e.nextSibling); + }); + }, + append() { + this.removeDuplicateTargetChildren(); + this.targetElements.forEach((e) => e.append(this.templateContent)); + }, + before() { + this.targetElements.forEach((e) => { + var _a; + return (_a = e.parentElement) === null || _a === void 0 ? void 0 : _a.insertBefore(this.templateContent, e); + }); + }, + prepend() { + this.removeDuplicateTargetChildren(); + this.targetElements.forEach((e) => e.prepend(this.templateContent)); + }, + remove() { + this.targetElements.forEach((e) => e.remove()); + }, + replace() { + this.targetElements.forEach((e) => e.replaceWith(this.templateContent)); + }, + update() { + this.targetElements.forEach((targetElement) => { + targetElement.innerHTML = ""; + targetElement.append(this.templateContent); + }); + } + }; + var session = new Session(); + var cache = new Cache(session); + var { navigator: navigator$1 } = session; + function start() { + session.start(); } - function waitForLoad(element, timeoutInMilliseconds = 2e3) { - return new Promise((resolve) => { - const onComplete = () => { - element.removeEventListener("error", onComplete); - element.removeEventListener("load", onComplete); - resolve(); - }; - element.addEventListener("load", onComplete, { once: true }); - element.addEventListener("error", onComplete, { once: true }); - setTimeout(resolve, timeoutInMilliseconds); - }); + function registerAdapter(adapter) { + session.registerAdapter(adapter); } - function getHistoryMethodForAction(action) { - switch (action) { - case "replace": - return history.replaceState; - case "advance": - case "restore": - return history.pushState; - } + function visit(location2, options) { + session.visit(location2, options); } - function isAction(action) { - return action == "advance" || action == "replace" || action == "restore"; + function connectStreamSource(source) { + session.connectStreamSource(source); } - function getVisitAction(...elements) { - const action = getAttribute("data-turbo-action", ...elements); - return isAction(action) ? action : null; + function disconnectStreamSource(source) { + session.disconnectStreamSource(source); } - function getMetaElement(name) { - return document.querySelector(`meta[name="${name}"]`); + function renderStreamMessage(message) { + session.renderStreamMessage(message); } - function getMetaContent(name) { - const element = getMetaElement(name); - return element && element.content; + function clearCache() { + console.warn("Please replace `Turbo.clearCache()` with `Turbo.cache.clear()`. The top-level function is deprecated and will be removed in a future version of Turbo.`"); + session.clearCache(); } - function setMetaContent(name, content) { - let element = getMetaElement(name); - if (!element) { - element = document.createElement("meta"); - element.setAttribute("name", name); - document.head.appendChild(element); - } - element.setAttribute("content", content); - return element; + function setProgressBarDelay(delay) { + session.setProgressBarDelay(delay); } - function findClosestRecursively(element, selector) { - var _a; - if (element instanceof Element) { - return element.closest(selector) || findClosestRecursively(element.assignedSlot || ((_a = element.getRootNode()) === null || _a === void 0 ? void 0 : _a.host), selector); - } + function setConfirmMethod(confirmMethod) { + FormSubmission.confirmMethod = confirmMethod; } - var FetchMethod; - (function(FetchMethod2) { - FetchMethod2[FetchMethod2["get"] = 0] = "get"; - FetchMethod2[FetchMethod2["post"] = 1] = "post"; - FetchMethod2[FetchMethod2["put"] = 2] = "put"; - FetchMethod2[FetchMethod2["patch"] = 3] = "patch"; - FetchMethod2[FetchMethod2["delete"] = 4] = "delete"; - })(FetchMethod || (FetchMethod = {})); - function fetchMethodFromString(method) { - switch (method.toLowerCase()) { - case "get": - return FetchMethod.get; - case "post": - return FetchMethod.post; - case "put": - return FetchMethod.put; - case "patch": - return FetchMethod.patch; - case "delete": - return FetchMethod.delete; - } + function setFormMode(mode) { + session.setFormMode(mode); } - var FetchRequest2 = class { - constructor(delegate, method, location2, body = new URLSearchParams(), target = null) { - this.abortController = new AbortController(); - this.resolveRequestPromise = (_value) => { + var Turbo2 = /* @__PURE__ */ Object.freeze({ + __proto__: null, + navigator: navigator$1, + session, + cache, + PageRenderer, + PageSnapshot, + FrameRenderer, + start, + registerAdapter, + visit, + connectStreamSource, + disconnectStreamSource, + renderStreamMessage, + clearCache, + setProgressBarDelay, + setConfirmMethod, + setFormMode, + StreamActions + }); + var TurboFrameMissingError = class extends Error { + }; + var FrameController = class { + constructor(element) { + this.fetchResponseLoaded = (_fetchResponse) => { }; - this.delegate = delegate; - this.method = method; - this.headers = this.defaultHeaders; - this.body = body; - this.url = location2; - this.target = target; + this.currentFetchRequest = null; + this.resolveVisitPromise = () => { + }; + this.connected = false; + this.hasBeenLoaded = false; + this.ignoredAttributes = /* @__PURE__ */ new Set(); + this.action = null; + this.visitCachedSnapshot = ({ element: element2 }) => { + const frame = element2.querySelector("#" + this.element.id); + if (frame && this.previousFrameElement) { + frame.replaceChildren(...this.previousFrameElement.children); + } + delete this.previousFrameElement; + }; + this.element = element; + this.view = new FrameView(this, this.element); + this.appearanceObserver = new AppearanceObserver(this, this.element); + this.formLinkClickObserver = new FormLinkClickObserver(this, this.element); + this.linkInterceptor = new LinkInterceptor(this, this.element); + this.restorationIdentifier = uuid(); + this.formSubmitObserver = new FormSubmitObserver(this, this.element); } - get location() { - return this.url; + connect() { + if (!this.connected) { + this.connected = true; + if (this.loadingStyle == FrameLoadingStyle.lazy) { + this.appearanceObserver.start(); + } else { + this.loadSourceURL(); + } + this.formLinkClickObserver.start(); + this.linkInterceptor.start(); + this.formSubmitObserver.start(); + } } - get params() { - return this.url.searchParams; + disconnect() { + if (this.connected) { + this.connected = false; + this.appearanceObserver.stop(); + this.formLinkClickObserver.stop(); + this.linkInterceptor.stop(); + this.formSubmitObserver.stop(); + } } - get entries() { - return this.body ? Array.from(this.body.entries()) : []; + disabledChanged() { + if (this.loadingStyle == FrameLoadingStyle.eager) { + this.loadSourceURL(); + } } - cancel() { - this.abortController.abort(); + sourceURLChanged() { + if (this.isIgnoringChangesTo("src")) + return; + if (this.element.isConnected) { + this.complete = false; + } + if (this.loadingStyle == FrameLoadingStyle.eager || this.hasBeenLoaded) { + this.loadSourceURL(); + } } - async perform() { - const { fetchOptions } = this; - this.delegate.prepareRequest(this); - await this.allowRequestToBeIntercepted(fetchOptions); + sourceURLReloaded() { + const { src } = this.element; + this.ignoringChangesToAttribute("complete", () => { + this.element.removeAttribute("complete"); + }); + this.element.src = null; + this.element.src = src; + return this.element.loaded; + } + completeChanged() { + if (this.isIgnoringChangesTo("complete")) + return; + this.loadSourceURL(); + } + loadingStyleChanged() { + if (this.loadingStyle == FrameLoadingStyle.lazy) { + this.appearanceObserver.start(); + } else { + this.appearanceObserver.stop(); + this.loadSourceURL(); + } + } + async loadSourceURL() { + if (this.enabled && this.isActive && !this.complete && this.sourceURL) { + this.element.loaded = this.visit(expandURL(this.sourceURL)); + this.appearanceObserver.stop(); + await this.element.loaded; + this.hasBeenLoaded = true; + } + } + async loadResponse(fetchResponse) { + if (fetchResponse.redirected || fetchResponse.succeeded && fetchResponse.isHTML) { + this.sourceURL = fetchResponse.response.url; + } try { - this.delegate.requestStarted(this); - const response = await fetch(this.url.href, fetchOptions); - return await this.receive(response); - } catch (error2) { - if (error2.name !== "AbortError") { - if (this.willDelegateErrorHandling(error2)) { - this.delegate.requestErrored(this, error2); + const html = await fetchResponse.responseHTML; + if (html) { + const document2 = parseHTMLDocument(html); + const pageSnapshot = PageSnapshot.fromDocument(document2); + if (pageSnapshot.isVisitable) { + await this.loadFrameResponse(fetchResponse, document2); + } else { + await this.handleUnvisitableFrameResponse(fetchResponse); } - throw error2; } } finally { - this.delegate.requestFinished(this); + this.fetchResponseLoaded = () => { + }; } } - async receive(response) { - const fetchResponse = new FetchResponse2(response); - const event = dispatch("turbo:before-fetch-response", { - cancelable: true, - detail: { fetchResponse }, - target: this.target - }); - if (event.defaultPrevented) { - this.delegate.requestPreventedHandlingResponse(this, fetchResponse); - } else if (fetchResponse.succeeded) { - this.delegate.requestSucceededWithResponse(this, fetchResponse); - } else { - this.delegate.requestFailedWithResponse(this, fetchResponse); + elementAppearedInViewport(element) { + this.proposeVisitIfNavigatedWithAction(element, element); + this.loadSourceURL(); + } + willSubmitFormLinkToLocation(link) { + return this.shouldInterceptNavigation(link); + } + submittedFormLinkToLocation(link, _location, form) { + const frame = this.findFrameElement(link); + if (frame) + form.setAttribute("data-turbo-frame", frame.id); + } + shouldInterceptLinkClick(element, _location, _event) { + return this.shouldInterceptNavigation(element); + } + linkClickIntercepted(element, location2) { + this.navigateFrame(element, location2); + } + willSubmitForm(element, submitter) { + return element.closest("turbo-frame") == this.element && this.shouldInterceptNavigation(element, submitter); + } + formSubmitted(element, submitter) { + if (this.formSubmission) { + this.formSubmission.stop(); } - return fetchResponse; + this.formSubmission = new FormSubmission(this, element, submitter); + const { fetchRequest } = this.formSubmission; + this.prepareRequest(fetchRequest); + this.formSubmission.start(); } - get fetchOptions() { + prepareRequest(request) { var _a; - return { - method: FetchMethod[this.method].toUpperCase(), - credentials: "same-origin", - headers: this.headers, - redirect: "follow", - body: this.isSafe ? null : this.body, - signal: this.abortSignal, - referrer: (_a = this.delegate.referrer) === null || _a === void 0 ? void 0 : _a.href - }; + request.headers["Turbo-Frame"] = this.id; + if ((_a = this.currentNavigationElement) === null || _a === void 0 ? void 0 : _a.hasAttribute("data-turbo-stream")) { + request.acceptResponseType(StreamMessage.contentType); + } } - get defaultHeaders() { - return { - Accept: "text/html, application/xhtml+xml" - }; + requestStarted(_request) { + markAsBusy(this.element); } - get isSafe() { - return this.method === FetchMethod.get; + requestPreventedHandlingResponse(_request, _response) { + this.resolveVisitPromise(); } - get abortSignal() { - return this.abortController.signal; + async requestSucceededWithResponse(request, response) { + await this.loadResponse(response); + this.resolveVisitPromise(); } - acceptResponseType(mimeType) { - this.headers["Accept"] = [mimeType, this.headers["Accept"]].join(", "); + async requestFailedWithResponse(request, response) { + await this.loadResponse(response); + this.resolveVisitPromise(); } - async allowRequestToBeIntercepted(fetchOptions) { - const requestInterception = new Promise((resolve) => this.resolveRequestPromise = resolve); - const event = dispatch("turbo:before-fetch-request", { - cancelable: true, - detail: { - fetchOptions, - url: this.url, - resume: this.resolveRequestPromise - }, - target: this.target - }); - if (event.defaultPrevented) - await requestInterception; + requestErrored(request, error2) { + console.error(error2); + this.resolveVisitPromise(); } - willDelegateErrorHandling(error2) { - const event = dispatch("turbo:fetch-request-error", { - target: this.target, - cancelable: true, - detail: { request: this, error: error2 } - }); - return !event.defaultPrevented; + requestFinished(_request) { + clearBusyState(this.element); } - }; - var AppearanceObserver = class { - constructor(delegate, element) { - this.started = false; - this.intersect = (entries) => { - const lastEntry = entries.slice(-1)[0]; - if (lastEntry === null || lastEntry === void 0 ? void 0 : lastEntry.isIntersecting) { - this.delegate.elementAppearedInViewport(this.element); - } - }; - this.delegate = delegate; - this.element = element; - this.intersectionObserver = new IntersectionObserver(this.intersect); + formSubmissionStarted({ formElement }) { + markAsBusy(formElement, this.findFrameElement(formElement)); } - start() { - if (!this.started) { - this.started = true; - this.intersectionObserver.observe(this.element); + formSubmissionSucceededWithResponse(formSubmission, response) { + const frame = this.findFrameElement(formSubmission.formElement, formSubmission.submitter); + frame.delegate.proposeVisitIfNavigatedWithAction(frame, formSubmission.formElement, formSubmission.submitter); + frame.delegate.loadResponse(response); + if (!formSubmission.isSafe) { + session.clearCache(); } } - stop() { - if (this.started) { - this.started = false; - this.intersectionObserver.unobserve(this.element); - } + formSubmissionFailedWithResponse(formSubmission, fetchResponse) { + this.element.delegate.loadResponse(fetchResponse); + session.clearCache(); } - }; - var StreamMessage = class { - static wrap(message) { - if (typeof message == "string") { - return new this(createDocumentFragment(message)); - } else { - return message; - } + formSubmissionErrored(formSubmission, error2) { + console.error(error2); } - constructor(fragment) { - this.fragment = importStreamElements(fragment); + formSubmissionFinished({ formElement }) { + clearBusyState(formElement, this.findFrameElement(formElement)); } - }; - StreamMessage.contentType = "text/vnd.turbo-stream.html"; - function importStreamElements(fragment) { - for (const element of fragment.querySelectorAll("turbo-stream")) { - const streamElement = document.importNode(element, true); - for (const inertScriptElement of streamElement.templateElement.content.querySelectorAll("script")) { - inertScriptElement.replaceWith(activateScriptElement(inertScriptElement)); + allowsImmediateRender({ element: newFrame }, options) { + const event = dispatch("turbo:before-frame-render", { + target: this.element, + detail: Object.assign({ newFrame }, options), + cancelable: true + }); + const { defaultPrevented, detail: { render } } = event; + if (this.view.renderer && render) { + this.view.renderer.renderElement = render; } - element.replaceWith(streamElement); + return !defaultPrevented; } - return fragment; - } - var FormSubmissionState; - (function(FormSubmissionState2) { - FormSubmissionState2[FormSubmissionState2["initialized"] = 0] = "initialized"; - FormSubmissionState2[FormSubmissionState2["requesting"] = 1] = "requesting"; - FormSubmissionState2[FormSubmissionState2["waiting"] = 2] = "waiting"; - FormSubmissionState2[FormSubmissionState2["receiving"] = 3] = "receiving"; - FormSubmissionState2[FormSubmissionState2["stopping"] = 4] = "stopping"; - FormSubmissionState2[FormSubmissionState2["stopped"] = 5] = "stopped"; - })(FormSubmissionState || (FormSubmissionState = {})); - var FormEnctype; - (function(FormEnctype2) { - FormEnctype2["urlEncoded"] = "application/x-www-form-urlencoded"; - FormEnctype2["multipart"] = "multipart/form-data"; - FormEnctype2["plain"] = "text/plain"; - })(FormEnctype || (FormEnctype = {})); - function formEnctypeFromString(encoding) { - switch (encoding.toLowerCase()) { - case FormEnctype.multipart: - return FormEnctype.multipart; - case FormEnctype.plain: - return FormEnctype.plain; - default: - return FormEnctype.urlEncoded; + viewRenderedSnapshot(_snapshot, _isPreview) { } - } - var FormSubmission = class { - static confirmMethod(message, _element, _submitter) { - return Promise.resolve(confirm(message)); + preloadOnLoadLinksForView(element) { + session.preloadOnLoadLinksForView(element); } - constructor(delegate, formElement, submitter, mustRedirect = false) { - this.state = FormSubmissionState.initialized; - this.delegate = delegate; - this.formElement = formElement; - this.submitter = submitter; - this.formData = buildFormData(formElement, submitter); - this.location = expandURL(this.action); - if (this.method == FetchMethod.get) { - mergeFormDataEntries(this.location, [...this.body.entries()]); + viewInvalidated() { + } + willRenderFrame(currentElement, _newElement) { + this.previousFrameElement = currentElement.cloneNode(true); + } + async loadFrameResponse(fetchResponse, document2) { + const newFrameElement = await this.extractForeignFrameElement(document2.body); + if (newFrameElement) { + const snapshot = new Snapshot(newFrameElement); + const renderer = new FrameRenderer(this, this.view.snapshot, snapshot, FrameRenderer.renderElement, false, false); + if (this.view.renderPromise) + await this.view.renderPromise; + this.changeHistory(); + await this.view.render(renderer); + this.complete = true; + session.frameRendered(fetchResponse, this.element); + session.frameLoaded(this.element); + this.fetchResponseLoaded(fetchResponse); + } else if (this.willHandleFrameMissingFromResponse(fetchResponse)) { + this.handleFrameMissingFromResponse(fetchResponse); } - this.fetchRequest = new FetchRequest2(this, this.method, this.location, this.body, this.formElement); - this.mustRedirect = mustRedirect; } - get method() { + async visit(url) { var _a; - const method = ((_a = this.submitter) === null || _a === void 0 ? void 0 : _a.getAttribute("formmethod")) || this.formElement.getAttribute("method") || ""; - return fetchMethodFromString(method.toLowerCase()) || FetchMethod.get; + const request = new FetchRequest(this, FetchMethod.get, url, new URLSearchParams(), this.element); + (_a = this.currentFetchRequest) === null || _a === void 0 ? void 0 : _a.cancel(); + this.currentFetchRequest = request; + return new Promise((resolve) => { + this.resolveVisitPromise = () => { + this.resolveVisitPromise = () => { + }; + this.currentFetchRequest = null; + resolve(); + }; + request.perform(); + }); } - get action() { - var _a; - const formElementAction = typeof this.formElement.action === "string" ? this.formElement.action : null; - if ((_a = this.submitter) === null || _a === void 0 ? void 0 : _a.hasAttribute("formaction")) { - return this.submitter.getAttribute("formaction") || ""; - } else { - return this.formElement.getAttribute("action") || formElementAction || ""; + navigateFrame(element, url, submitter) { + const frame = this.findFrameElement(element, submitter); + frame.delegate.proposeVisitIfNavigatedWithAction(frame, element, submitter); + this.withCurrentNavigationElement(element, () => { + frame.src = url; + }); + } + proposeVisitIfNavigatedWithAction(frame, element, submitter) { + this.action = getVisitAction(submitter, element, frame); + if (this.action) { + const pageSnapshot = PageSnapshot.fromElement(frame).clone(); + const { visitCachedSnapshot } = frame.delegate; + frame.delegate.fetchResponseLoaded = (fetchResponse) => { + if (frame.src) { + const { statusCode, redirected } = fetchResponse; + const responseHTML = frame.ownerDocument.documentElement.outerHTML; + const response = { statusCode, redirected, responseHTML }; + const options = { + response, + visitCachedSnapshot, + willRender: false, + updateHistory: false, + restorationIdentifier: this.restorationIdentifier, + snapshot: pageSnapshot + }; + if (this.action) + options.action = this.action; + session.visit(frame.src, options); + } + }; } } - get body() { - if (this.enctype == FormEnctype.urlEncoded || this.method == FetchMethod.get) { - return new URLSearchParams(this.stringFormData); - } else { - return this.formData; + changeHistory() { + if (this.action) { + const method = getHistoryMethodForAction(this.action); + session.history.update(method, expandURL(this.element.src || ""), this.restorationIdentifier); } } - get enctype() { - var _a; - return formEnctypeFromString(((_a = this.submitter) === null || _a === void 0 ? void 0 : _a.getAttribute("formenctype")) || this.formElement.enctype); + async handleUnvisitableFrameResponse(fetchResponse) { + console.warn(`The response (${fetchResponse.statusCode}) from is performing a full page visit due to turbo-visit-control.`); + await this.visitResponse(fetchResponse.response); } - get isSafe() { - return this.fetchRequest.isSafe; + willHandleFrameMissingFromResponse(fetchResponse) { + this.element.setAttribute("complete", ""); + const response = fetchResponse.response; + const visit2 = async (url, options = {}) => { + if (url instanceof Response) { + this.visitResponse(url); + } else { + session.visit(url, options); + } + }; + const event = dispatch("turbo:frame-missing", { + target: this.element, + detail: { response, visit: visit2 }, + cancelable: true + }); + return !event.defaultPrevented; } - get stringFormData() { - return [...this.formData].reduce((entries, [name, value]) => { - return entries.concat(typeof value == "string" ? [[name, value]] : []); - }, []); + handleFrameMissingFromResponse(fetchResponse) { + this.view.missing(); + this.throwFrameMissingError(fetchResponse); } - async start() { - const { initialized, requesting } = FormSubmissionState; - const confirmationMessage = getAttribute("data-turbo-confirm", this.submitter, this.formElement); - if (typeof confirmationMessage === "string") { - const answer = await FormSubmission.confirmMethod(confirmationMessage, this.formElement, this.submitter); - if (!answer) { - return; + throwFrameMissingError(fetchResponse) { + const message = `The response (${fetchResponse.statusCode}) did not contain the expected and will be ignored. To perform a full page visit instead, set turbo-visit-control to reload.`; + throw new TurboFrameMissingError(message); + } + async visitResponse(response) { + const wrapped = new FetchResponse(response); + const responseHTML = await wrapped.responseHTML; + const { location: location2, redirected, statusCode } = wrapped; + return session.visit(location2, { response: { redirected, statusCode, responseHTML } }); + } + findFrameElement(element, submitter) { + var _a; + const id = getAttribute("data-turbo-frame", submitter, element) || this.element.getAttribute("target"); + return (_a = getFrameElementById(id)) !== null && _a !== void 0 ? _a : this.element; + } + async extractForeignFrameElement(container) { + let element; + const id = CSS.escape(this.id); + try { + element = activateElement(container.querySelector(`turbo-frame#${id}`), this.sourceURL); + if (element) { + return element; } + element = activateElement(container.querySelector(`turbo-frame[src][recurse~=${id}]`), this.sourceURL); + if (element) { + await element.loaded; + return await this.extractForeignFrameElement(element); + } + } catch (error2) { + console.error(error2); + return new FrameElement(); } - if (this.state == initialized) { - this.state = requesting; - return this.fetchRequest.perform(); - } + return null; } - stop() { - const { stopping, stopped } = FormSubmissionState; - if (this.state != stopping && this.state != stopped) { - this.state = stopping; - this.fetchRequest.cancel(); - return true; - } + formActionIsVisitable(form, submitter) { + const action = getAction(form, submitter); + return locationIsVisitable(expandURL(action), this.rootLocation); } - prepareRequest(request) { - if (!request.isSafe) { - const token = getCookieValue(getMetaContent("csrf-param")) || getMetaContent("csrf-token"); - if (token) { - request.headers["X-CSRF-Token"] = token; + shouldInterceptNavigation(element, submitter) { + const id = getAttribute("data-turbo-frame", submitter, element) || this.element.getAttribute("target"); + if (element instanceof HTMLFormElement && !this.formActionIsVisitable(element, submitter)) { + return false; + } + if (!this.enabled || id == "_top") { + return false; + } + if (id) { + const frameElement = getFrameElementById(id); + if (frameElement) { + return !frameElement.disabled; } } - if (this.requestAcceptsTurboStreamResponse(request)) { - request.acceptResponseType(StreamMessage.contentType); + if (!session.elementIsNavigatable(element)) { + return false; + } + if (submitter && !session.elementIsNavigatable(submitter)) { + return false; } + return true; } - requestStarted(_request) { - var _a; - this.state = FormSubmissionState.waiting; - (_a = this.submitter) === null || _a === void 0 ? void 0 : _a.setAttribute("disabled", ""); - this.setSubmitsWith(); - dispatch("turbo:submit-start", { - target: this.formElement, - detail: { formSubmission: this } - }); - this.delegate.formSubmissionStarted(this); + get id() { + return this.element.id; } - requestPreventedHandlingResponse(request, response) { - this.result = { success: response.succeeded, fetchResponse: response }; + get enabled() { + return !this.element.disabled; } - requestSucceededWithResponse(request, response) { - if (response.clientError || response.serverError) { - this.delegate.formSubmissionFailedWithResponse(this, response); - } else if (this.requestMustRedirect(request) && responseSucceededWithoutRedirect(response)) { - const error2 = new Error("Form responses must redirect to another location"); - this.delegate.formSubmissionErrored(this, error2); - } else { - this.state = FormSubmissionState.receiving; - this.result = { success: true, fetchResponse: response }; - this.delegate.formSubmissionSucceededWithResponse(this, response); + get sourceURL() { + if (this.element.src) { + return this.element.src; } } - requestFailedWithResponse(request, response) { - this.result = { success: false, fetchResponse: response }; - this.delegate.formSubmissionFailedWithResponse(this, response); + set sourceURL(sourceURL) { + this.ignoringChangesToAttribute("src", () => { + this.element.src = sourceURL !== null && sourceURL !== void 0 ? sourceURL : null; + }); } - requestErrored(request, error2) { - this.result = { success: false, error: error2 }; - this.delegate.formSubmissionErrored(this, error2); + get loadingStyle() { + return this.element.loading; } - requestFinished(_request) { - var _a; - this.state = FormSubmissionState.stopped; - (_a = this.submitter) === null || _a === void 0 ? void 0 : _a.removeAttribute("disabled"); - this.resetSubmitterText(); - dispatch("turbo:submit-end", { - target: this.formElement, - detail: Object.assign({ formSubmission: this }, this.result) - }); - this.delegate.formSubmissionFinished(this); + get isLoading() { + return this.formSubmission !== void 0 || this.resolveVisitPromise() !== void 0; } - setSubmitsWith() { - if (!this.submitter || !this.submitsWith) - return; - if (this.submitter.matches("button")) { - this.originalSubmitText = this.submitter.innerHTML; - this.submitter.innerHTML = this.submitsWith; - } else if (this.submitter.matches("input")) { - const input = this.submitter; - this.originalSubmitText = input.value; - input.value = this.submitsWith; - } - } - resetSubmitterText() { - if (!this.submitter || !this.originalSubmitText) - return; - if (this.submitter.matches("button")) { - this.submitter.innerHTML = this.originalSubmitText; - } else if (this.submitter.matches("input")) { - const input = this.submitter; - input.value = this.originalSubmitText; - } + get complete() { + return this.element.hasAttribute("complete"); } - requestMustRedirect(request) { - return !request.isSafe && this.mustRedirect; + set complete(value) { + this.ignoringChangesToAttribute("complete", () => { + if (value) { + this.element.setAttribute("complete", ""); + } else { + this.element.removeAttribute("complete"); + } + }); } - requestAcceptsTurboStreamResponse(request) { - return !request.isSafe || hasAttribute("data-turbo-stream", this.submitter, this.formElement); + get isActive() { + return this.element.isActive && this.connected; } - get submitsWith() { + get rootLocation() { var _a; - return (_a = this.submitter) === null || _a === void 0 ? void 0 : _a.getAttribute("data-turbo-submits-with"); + const meta = this.element.ownerDocument.querySelector(`meta[name="turbo-root"]`); + const root = (_a = meta === null || meta === void 0 ? void 0 : meta.content) !== null && _a !== void 0 ? _a : "/"; + return expandURL(root); } - }; - function buildFormData(formElement, submitter) { - const formData = new FormData(formElement); - const name = submitter === null || submitter === void 0 ? void 0 : submitter.getAttribute("name"); - const value = submitter === null || submitter === void 0 ? void 0 : submitter.getAttribute("value"); - if (name) { - formData.append(name, value || ""); + isIgnoringChangesTo(attributeName) { + return this.ignoredAttributes.has(attributeName); } - return formData; - } - function getCookieValue(cookieName) { - if (cookieName != null) { - const cookies = document.cookie ? document.cookie.split("; ") : []; - const cookie = cookies.find((cookie2) => cookie2.startsWith(cookieName)); - if (cookie) { - const value = cookie.split("=").slice(1).join("="); - return value ? decodeURIComponent(value) : void 0; + ignoringChangesToAttribute(attributeName, callback) { + this.ignoredAttributes.add(attributeName); + callback(); + this.ignoredAttributes.delete(attributeName); + } + withCurrentNavigationElement(element, callback) { + this.currentNavigationElement = element; + callback(); + delete this.currentNavigationElement; + } + }; + function getFrameElementById(id) { + if (id != null) { + const element = document.getElementById(id); + if (element instanceof FrameElement) { + return element; } } } - function responseSucceededWithoutRedirect(response) { - return response.statusCode == 200 && !response.redirected; - } - function mergeFormDataEntries(url, entries) { - const searchParams = new URLSearchParams(); - for (const [name, value] of entries) { - if (value instanceof File) - continue; - searchParams.append(name, value); + function activateElement(element, currentURL) { + if (element) { + const src = element.getAttribute("src"); + if (src != null && currentURL != null && urlsAreEqual(src, currentURL)) { + throw new Error(`Matching element has a source URL which references itself`); + } + if (element.ownerDocument !== document) { + element = document.importNode(element, true); + } + if (element instanceof FrameElement) { + element.connectedCallback(); + element.disconnectedCallback(); + return element; + } } - url.search = searchParams.toString(); - return url; } - var Snapshot = class { - constructor(element) { - this.element = element; - } - get activeElement() { - return this.element.ownerDocument.activeElement; - } - get children() { - return [...this.element.children]; - } - hasAnchor(anchor) { - return this.getElementForAnchor(anchor) != null; + var StreamElement = class extends HTMLElement { + static async renderElement(newElement) { + await newElement.performAction(); } - getElementForAnchor(anchor) { - return anchor ? this.element.querySelector(`[id='${anchor}'], a[name='${anchor}']`) : null; + async connectedCallback() { + try { + await this.render(); + } catch (error2) { + console.error(error2); + } finally { + this.disconnect(); + } } - get isConnected() { - return this.element.isConnected; + async render() { + var _a; + return (_a = this.renderPromise) !== null && _a !== void 0 ? _a : this.renderPromise = (async () => { + const event = this.beforeRenderEvent; + if (this.dispatchEvent(event)) { + await nextAnimationFrame(); + await event.detail.render(this); + } + })(); } - get firstAutofocusableElement() { - const inertDisabledOrHidden = "[inert], :disabled, [hidden], details:not([open]), dialog:not([open])"; - for (const element of this.element.querySelectorAll("[autofocus]")) { - if (element.closest(inertDisabledOrHidden) == null) - return element; - else - continue; + disconnect() { + try { + this.remove(); + } catch (_a) { } - return null; } - get permanentElements() { - return queryPermanentElementsAll(this.element); + removeDuplicateTargetChildren() { + this.duplicateChildren.forEach((c) => c.remove()); } - getPermanentElementById(id) { - return getPermanentElementById(this.element, id); + get duplicateChildren() { + var _a; + const existingChildren = this.targetElements.flatMap((e) => [...e.children]).filter((c) => !!c.id); + const newChildrenIds = [...((_a = this.templateContent) === null || _a === void 0 ? void 0 : _a.children) || []].filter((c) => !!c.id).map((c) => c.id); + return existingChildren.filter((c) => newChildrenIds.includes(c.id)); } - getPermanentElementMapForSnapshot(snapshot) { - const permanentElementMap = {}; - for (const currentPermanentElement of this.permanentElements) { - const { id } = currentPermanentElement; - const newPermanentElement = snapshot.getPermanentElementById(id); - if (newPermanentElement) { - permanentElementMap[id] = [currentPermanentElement, newPermanentElement]; + get performAction() { + if (this.action) { + const actionFunction = StreamActions[this.action]; + if (actionFunction) { + return actionFunction; } + this.raise("unknown action"); } - return permanentElementMap; - } - }; - function getPermanentElementById(node, id) { - return node.querySelector(`#${id}[data-turbo-permanent]`); - } - function queryPermanentElementsAll(node) { - return node.querySelectorAll("[id][data-turbo-permanent]"); - } - var FormSubmitObserver = class { - constructor(delegate, eventTarget) { - this.started = false; - this.submitCaptured = () => { - this.eventTarget.removeEventListener("submit", this.submitBubbled, false); - this.eventTarget.addEventListener("submit", this.submitBubbled, false); - }; - this.submitBubbled = (event) => { - if (!event.defaultPrevented) { - const form = event.target instanceof HTMLFormElement ? event.target : void 0; - const submitter = event.submitter || void 0; - if (form && submissionDoesNotDismissDialog(form, submitter) && submissionDoesNotTargetIFrame(form, submitter) && this.delegate.willSubmitForm(form, submitter)) { - event.preventDefault(); - event.stopImmediatePropagation(); - this.delegate.formSubmitted(form, submitter); - } - } - }; - this.delegate = delegate; - this.eventTarget = eventTarget; + this.raise("action attribute is missing"); } - start() { - if (!this.started) { - this.eventTarget.addEventListener("submit", this.submitCaptured, true); - this.started = true; + get targetElements() { + if (this.target) { + return this.targetElementsById; + } else if (this.targets) { + return this.targetElementsByQuery; + } else { + this.raise("target or targets attribute is missing"); } } - stop() { - if (this.started) { - this.eventTarget.removeEventListener("submit", this.submitCaptured, true); - this.started = false; - } + get templateContent() { + return this.templateElement.content.cloneNode(true); } - }; - function submissionDoesNotDismissDialog(form, submitter) { - const method = (submitter === null || submitter === void 0 ? void 0 : submitter.getAttribute("formmethod")) || form.getAttribute("method"); - return method != "dialog"; - } - function submissionDoesNotTargetIFrame(form, submitter) { - if ((submitter === null || submitter === void 0 ? void 0 : submitter.hasAttribute("formtarget")) || form.hasAttribute("target")) { - const target = (submitter === null || submitter === void 0 ? void 0 : submitter.getAttribute("formtarget")) || form.target; - for (const element of document.getElementsByName(target)) { - if (element instanceof HTMLIFrameElement) - return false; + get templateElement() { + if (this.firstElementChild === null) { + const template = this.ownerDocument.createElement("template"); + this.appendChild(template); + return template; + } else if (this.firstElementChild instanceof HTMLTemplateElement) { + return this.firstElementChild; } - return true; - } else { - return true; + this.raise("first child element must be a