chrono_cable 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +69 -0
- data/Rakefile +6 -0
- data/app/assets/javascripts/chronocable.js +607 -0
- data/app/assets/javascripts/chronocable_turbo.js +5970 -0
- data/app/assets/javascripts/chronocable_turbo.min.js +29 -0
- data/app/javascript/action_cable/adapters.js +4 -0
- data/app/javascript/action_cable/connection.js +183 -0
- data/app/javascript/action_cable/connection_monitor.js +124 -0
- data/app/javascript/action_cable/consumer.js +80 -0
- data/app/javascript/action_cable/index.js +33 -0
- data/app/javascript/action_cable/internal.js +21 -0
- data/app/javascript/action_cable/logger.js +22 -0
- data/app/javascript/action_cable/stream.js +73 -0
- data/app/javascript/action_cable/subscription.js +103 -0
- data/app/javascript/action_cable/subscription_guarantor.js +50 -0
- data/app/javascript/action_cable/subscriptions.js +141 -0
- data/app/javascript/turbo/cable.js +19 -0
- data/app/javascript/turbo/cable_stream_source_element.js +53 -0
- data/app/javascript/turbo/fetch_requests.js +59 -0
- data/app/javascript/turbo/index.js +13 -0
- data/app/javascript/turbo/snakeize.js +31 -0
- data/app/models/chrono_cable/application_record.rb +5 -0
- data/app/models/solid_cable/channel.rb +12 -0
- data/db/migrate/20260628205427_create_solid_cable_channels.rb +12 -0
- data/db/migrate/20260629194211_add_channel_id_to_solid_cable_messages.rb +7 -0
- data/lib/action_cable/subscription_adapter/message.rb +12 -0
- data/lib/chrono_cable/channel_base.rb +30 -0
- data/lib/chrono_cable/channel_streams.rb +121 -0
- data/lib/chrono_cable/connection_subscriptions.rb +16 -0
- data/lib/chrono_cable/engine.rb +11 -0
- data/lib/chrono_cable/solid_cable_adapter.rb +26 -0
- data/lib/chrono_cable/solid_cable_adapter_listener.rb +28 -0
- data/lib/chrono_cable/solid_cable_broadcasting.rb +19 -0
- data/lib/chrono_cable/solid_cable_message_class_methods.rb +9 -0
- data/lib/chrono_cable/subscription_adapter_base_extensions.rb +5 -0
- data/lib/chrono_cable/turbo_streams_channel.rb +5 -0
- data/lib/chrono_cable/version.rb +3 -0
- data/lib/chrono_cable.rb +38 -0
- data/lib/generators/chrono_cable/install/USAGE +9 -0
- data/lib/generators/chrono_cable/install/install_generator.rb +32 -0
- data/lib/generators/chrono_cable/install/templates/add_channel_id_to_solid_cable_messages.rb +7 -0
- data/lib/generators/chrono_cable/install/templates/create_solid_cable_channels.rb +12 -0
- data/lib/tasks/chrono_cable_tasks.rake +6 -0
- metadata +116 -0
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
var Es=Object.defineProperty;var As=(e)=>e;function Ts(e,t){this[e]=As.bind(null,t)}var rt=(e,t)=>{for(var s in t)Es(e,s,{get:t[s],enumerable:!0,configurable:!0,set:Ts.bind(t,s)})};var Ke={};rt(Ke,{FetchEnctype:()=>x,FetchMethod:()=>P,FetchRequest:()=>j,FetchResponse:()=>ie,FrameElement:()=>k,FrameLoadingStyle:()=>U,FrameRenderer:()=>oe,PageRenderer:()=>ce,PageSnapshot:()=>I,StreamActions:()=>Ge,StreamElement:()=>Ce,StreamSourceElement:()=>Je,cache:()=>es,config:()=>C,connectStreamSource:()=>le,disconnectStreamSource:()=>he,fetch:()=>Oe,fetchEnctypeFromString:()=>Tt,fetchMethodFromString:()=>ye,isSafe:()=>Ee,morphBodyElements:()=>cs,morphChildren:()=>Le,morphElements:()=>ae,morphTurboFrameElements:()=>ls,navigator:()=>ts,registerAdapter:()=>ss,renderStreamMessage:()=>is,session:()=>L,setConfirmMethod:()=>os,setFormMode:()=>as,setProgressBarDelay:()=>ns,start:()=>je,visit:()=>rs});/*!
|
|
2
|
+
Turbo 8.0.23
|
|
3
|
+
Copyright © 2026 37signals LLC
|
|
4
|
+
*/var U={eager:"eager",lazy:"lazy"};class k extends HTMLElement{static delegateConstructor=void 0;loaded=Promise.resolve();static get observedAttributes(){return["disabled","loading","src"]}constructor(){super();this.delegate=new k.delegateConstructor(this)}connectedCallback(){this.delegate.connect()}disconnectedCallback(){this.delegate.disconnect()}reload(){return this.delegate.sourceURLReloaded()}attributeChangedCallback(e){if(e=="loading")this.delegate.loadingStyleChanged();else if(e=="src")this.delegate.sourceURLChanged();else if(e=="disabled")this.delegate.disabledChanged()}get src(){return this.getAttribute("src")}set src(e){if(e)this.setAttribute("src",e);else this.removeAttribute("src")}get refresh(){return this.getAttribute("refresh")}set refresh(e){if(e)this.setAttribute("refresh",e);else this.removeAttribute("refresh")}get shouldReloadWithMorph(){return this.src&&this.refresh==="morph"}get loading(){return Rs(this.getAttribute("loading")||"")}set loading(e){if(e)this.setAttribute("loading",e);else this.removeAttribute("loading")}get disabled(){return this.hasAttribute("disabled")}set disabled(e){if(e)this.setAttribute("disabled","");else this.removeAttribute("disabled")}get autoscroll(){return this.hasAttribute("autoscroll")}set autoscroll(e){if(e)this.setAttribute("autoscroll","");else this.removeAttribute("autoscroll")}get complete(){return!this.delegate.isLoading}get isActive(){return this.ownerDocument===document&&!this.isPreview}get isPreview(){return this.ownerDocument?.documentElement?.hasAttribute("data-turbo-preview")}}function Rs(e){switch(e.toLowerCase()){case"lazy":return U.lazy;default:return U.eager}}var Ls={enabled:!0,progressBarDelay:500,unvisitableExtensions:new Set([".7z",".aac",".apk",".avi",".bmp",".bz2",".css",".csv",".deb",".dmg",".doc",".docx",".exe",".gif",".gz",".heic",".heif",".ico",".iso",".jpeg",".jpg",".js",".json",".m4a",".mkv",".mov",".mp3",".mp4",".mpeg",".mpg",".msi",".ogg",".ogv",".pdf",".pkg",".png",".ppt",".pptx",".rar",".rtf",".svg",".tar",".tif",".tiff",".txt",".wav",".webm",".webp",".wma",".wmv",".xls",".xlsx",".xml",".zip"])};function re(e){if(e.getAttribute("data-turbo-eval")=="false")return e;else{let t=document.createElement("script"),s=pt();if(s)t.nonce=s;return t.textContent=e.textContent,t.async=!1,Cs(t,e),t}}function Cs(e,t){for(let{name:s,value:r}of t.attributes)e.setAttribute(s,r)}function Ms(e){let t=document.createElement("template");return t.innerHTML=e,t.content}function R(e,{target:t,cancelable:s,detail:r}={}){let i=new CustomEvent(e,{cancelable:s,bubbles:!0,composed:!0,detail:r});if(t&&t.isConnected)t.dispatchEvent(i);else document.documentElement.dispatchEvent(i);return i}function it(e){e.preventDefault(),e.stopImmediatePropagation()}function te(){if(document.visibilityState==="hidden")return ut();else return ht()}function ht(){return new Promise((e)=>requestAnimationFrame(()=>e()))}function ut(){return new Promise((e)=>setTimeout(()=>e(),0))}function dt(e=""){return new DOMParser().parseFromString(e,"text/html")}function mt(e,...t){let s=Ps(e,t).replace(/^\n/,"").split(`
|
|
5
|
+
`),r=s[0].match(/^\s+/),i=r?r[0].length:0;return s.map((l)=>l.slice(i)).join(`
|
|
6
|
+
`)}function Ps(e,t){return e.reduce((s,r,i)=>{let l=t[i]==null?"":t[i];return s+r+l},"")}function V(){return Array.from({length:36}).map((e,t)=>{if(t==8||t==13||t==18||t==23)return"-";else if(t==14)return"4";else if(t==19)return(Math.floor(Math.random()*4)+8).toString(16);else return Math.floor(Math.random()*16).toString(16)}).join("")}function be(e,...t){for(let s of t.map((r)=>r?.getAttribute(e)))if(typeof s=="string")return s;return null}function ks(e,...t){return t.some((s)=>s&&s.hasAttribute(e))}function ve(...e){for(let t of e){if(t.localName=="turbo-frame")t.setAttribute("busy","");t.setAttribute("aria-busy","true")}}function Se(...e){for(let t of e){if(t.localName=="turbo-frame")t.removeAttribute("busy");t.removeAttribute("aria-busy")}}function Is(e,t=2000){return new Promise((s)=>{let r=()=>{e.removeEventListener("error",r),e.removeEventListener("load",r),s()};e.addEventListener("load",r,{once:!0}),e.addEventListener("error",r,{once:!0}),setTimeout(s,t)})}function ft(e){switch(e){case"replace":return history.replaceState;case"advance":case"restore":return history.pushState}}function qs(e){return e=="advance"||e=="replace"||e=="restore"}function z(...e){let t=be("data-turbo-action",...e);return qs(t)?t:null}function Fe(e){return document.querySelector(`meta[name="${e}"]`)}function we(e){let t=Fe(e);return t&&t.content}function pt(){let e=Fe("csp-nonce");if(e){let{nonce:t,content:s}=e;return t==""?s:t}}function Hs(e,t){let s=Fe(e);if(!s)s=document.createElement("meta"),s.setAttribute("name",e),document.head.appendChild(s);return s.setAttribute("content",t),s}function Q(e,t){if(e instanceof Element)return e.closest(t)||Q(e.assignedSlot||e.getRootNode()?.host,t)}function Be(e){return!!e&&e.closest("[inert], :disabled, [hidden], details:not([open]), dialog:not([open])")==null&&typeof e.focus=="function"}function gt(e){return Array.from(e.querySelectorAll("[autofocus]")).find(Be)}async function Fs(e,t){let s=t();e(),await ht();let r=t();return[s,r]}function bt(e){if(e==="_blank")return!1;else if(e){for(let t of document.getElementsByName(e))if(t instanceof HTMLIFrameElement)return!1;return!0}else return!0}function vt(e){let t=Q(e,"a[href], a[xlink\\:href]");if(!t)return null;if(t.href.startsWith("#"))return null;if(t.hasAttribute("download"))return null;let s=t.getAttribute("target");if(s&&s!=="_self")return null;return t}function Bs(e,t){let s=null;return(...r)=>{let i=()=>e.apply(this,r);clearTimeout(s),s=setTimeout(i,t)}}var Ds={"aria-disabled":{beforeSubmit:(e)=>{e.setAttribute("aria-disabled","true"),e.addEventListener("click",it)},afterSubmit:(e)=>{e.removeAttribute("aria-disabled"),e.removeEventListener("click",it)}},disabled:{beforeSubmit:(e)=>e.disabled=!0,afterSubmit:(e)=>e.disabled=!1}};class St{#e=null;constructor(e){Object.assign(this,e)}get submitter(){return this.#e}set submitter(e){this.#e=Ds[e]||e}}var Os=new St({mode:"on",submitter:"disabled"}),C={drive:Ls,forms:Os};function M(e){return new URL(e.toString(),document.baseURI)}function se(e){let t;if(e.hash)return e.hash.slice(1);else if(t=e.href.match(/#(.*)$/))return t[1]}function De(e,t){let s=t?.getAttribute("formaction")||e.getAttribute("action")||e.action;return M(s)}function Ns(e){return(_s(e).match(/\.[^.]*$/)||[])[0]||""}function xs(e,t){let s=nt(t.origin+t.pathname);return nt(e.href)===s||e.href.startsWith(s)}function N(e,t){return xs(e,t)&&!C.drive.unvisitableExtensions.has(Ns(e))}function wt(e){return M(e.getAttribute("href")||"")}function Vs(e){let t=se(e);return t!=null?e.href.slice(0,-(t.length+1)):e.href}function ge(e){return Vs(e)}function yt(e,t){return M(e).href==M(t).href}function Ws(e){return e.pathname.split("/").slice(1)}function _s(e){return Ws(e).slice(-1)[0]}function nt(e){return e.endsWith("/")?e:e+"/"}class ie{constructor(e){this.response=e}get succeeded(){return this.response.ok}get failed(){return!this.succeeded}get clientError(){return this.statusCode>=400&&this.statusCode<=499}get serverError(){return this.statusCode>=500&&this.statusCode<=599}get redirected(){return this.response.redirected}get location(){return M(this.response.url)}get isHTML(){return this.contentType&&this.contentType.match(/^(?:text\/([^\s;,]+\b)?html|application\/xhtml\+xml)\b/)}get statusCode(){return this.response.status}get contentType(){return this.header("Content-Type")}get responseText(){return this.response.clone().text()}get responseHTML(){if(this.isHTML)return this.response.clone().text();else return Promise.resolve(void 0)}header(e){return this.response.headers.get(e)}}class Et extends Set{constructor(e){super();this.maxSize=e}add(e){if(this.size>=this.maxSize){let s=this.values().next().value;this.delete(s)}super.add(e)}}var At=new Et(20);function Oe(e,t={}){let s=new Headers(t.headers||{}),r=V();return At.add(r),s.append("X-Turbo-Request-Id",r),window.fetch(e,{...t,headers:s})}function ye(e){switch(e.toLowerCase()){case"get":return P.get;case"post":return P.post;case"put":return P.put;case"patch":return P.patch;case"delete":return P.delete}}var P={get:"get",post:"post",put:"put",patch:"patch",delete:"delete"};function Tt(e){switch(e.toLowerCase()){case x.multipart:return x.multipart;case x.plain:return x.plain;default:return x.urlEncoded}}var x={urlEncoded:"application/x-www-form-urlencoded",multipart:"multipart/form-data",plain:"text/plain"};class j{abortController=new AbortController;#e=(e)=>{};constructor(e,t,s,r=new URLSearchParams,i=null,l=x.urlEncoded){let[b,E]=ot(M(s),t,r,l);this.delegate=e,this.url=b,this.target=i,this.fetchOptions={credentials:"same-origin",redirect:"follow",method:t.toUpperCase(),headers:{...this.defaultHeaders},body:E,signal:this.abortSignal,referrer:this.delegate.referrer?.href},this.enctype=l}get method(){return this.fetchOptions.method}set method(e){let t=this.isSafe?this.url.searchParams:this.fetchOptions.body||new FormData,s=ye(e)||P.get;this.url.search="";let[r,i]=ot(this.url,s,t,this.enctype);this.url=r,this.fetchOptions.body=i,this.fetchOptions.method=s.toUpperCase()}get headers(){return this.fetchOptions.headers}set headers(e){this.fetchOptions.headers=e}get body(){if(this.isSafe)return this.url.searchParams;else return this.fetchOptions.body}set body(e){this.fetchOptions.body=e}get location(){return this.url}get params(){return this.url.searchParams}get entries(){return this.body?Array.from(this.body.entries()):[]}cancel(){this.abortController.abort()}async perform(){let{fetchOptions:e}=this;this.delegate.prepareRequest(this);let t=await this.#t(e);try{if(this.delegate.requestStarted(this),t.detail.fetchRequest)this.response=t.detail.fetchRequest.response;else this.response=Oe(this.url.href,e);let s=await this.response;return await this.receive(s)}catch(s){if(s.name!=="AbortError"){if(this.#s(s))this.delegate.requestErrored(this,s);throw s}}finally{this.delegate.requestFinished(this)}}async receive(e){let t=new ie(e);if(R("turbo:before-fetch-response",{cancelable:!0,detail:{fetchResponse:t},target:this.target}).defaultPrevented)this.delegate.requestPreventedHandlingResponse(this,t);else if(t.succeeded)this.delegate.requestSucceededWithResponse(this,t);else this.delegate.requestFailedWithResponse(this,t);return t}get defaultHeaders(){return{Accept:"text/html, application/xhtml+xml"}}get isSafe(){return Ee(this.method)}get abortSignal(){return this.abortController.signal}acceptResponseType(e){this.headers.Accept=[e,this.headers.Accept].join(", ")}async#t(e){let t=new Promise((r)=>this.#e=r),s=R("turbo:before-fetch-request",{cancelable:!0,detail:{fetchOptions:e,url:this.url,resume:this.#e},target:this.target});if(this.url=s.detail.url,s.defaultPrevented)await t;return s}#s(e){return!R("turbo:fetch-request-error",{target:this.target,cancelable:!0,detail:{request:this,error:e}}).defaultPrevented}}function Ee(e){return ye(e)==P.get}function ot(e,t,s,r){let i=Array.from(s).length>0?new URLSearchParams(Rt(s)):e.searchParams;if(Ee(t))return[Us(e,i),null];else if(r==x.urlEncoded)return[e,i];else return[e,s]}function Rt(e){let t=[];for(let[s,r]of e)if(r instanceof File)continue;else t.push([s,r]);return t}function Us(e,t){let s=new URLSearchParams(Rt(t));return e.search=s.toString(),e}class Lt{started=!1;constructor(e,t){this.delegate=e,this.element=t,this.intersectionObserver=new IntersectionObserver(this.intersect)}start(){if(!this.started)this.started=!0,this.intersectionObserver.observe(this.element)}stop(){if(this.started)this.started=!1,this.intersectionObserver.unobserve(this.element)}intersect=(e)=>{if(e.slice(-1)[0]?.isIntersecting)this.delegate.elementAppearedInViewport(this.element)}}class G{static contentType="text/vnd.turbo-stream.html";static wrap(e){if(typeof e=="string")return new this(Ms(e));else return e}constructor(e){this.fragment=$s(e)}}function $s(e){for(let t of e.querySelectorAll("turbo-stream")){let s=document.importNode(t,!0);for(let r of s.templateElement.content.querySelectorAll("script"))r.replaceWith(re(r));t.replaceWith(s)}return e}var zs=(e)=>e;class Ne{keys=[];entries={};#e;constructor(e,t=zs){this.size=e,this.#e=t}has(e){return this.#e(e)in this.entries}get(e){if(this.has(e)){let t=this.read(e);return this.touch(e),t}}put(e,t){return this.write(e,t),this.touch(e),t}clear(){for(let e of Object.keys(this.entries))this.evict(e)}read(e){return this.entries[this.#e(e)]}write(e,t){this.entries[this.#e(e)]=t}touch(e){e=this.#e(e);let t=this.keys.indexOf(e);if(t>-1)this.keys.splice(t,1);this.keys.unshift(e),this.trim()}trim(){for(let e of this.keys.splice(this.size))this.evict(e)}evict(e){delete this.entries[e]}}var js=100;class Ct extends Ne{#e=null;#t={};constructor(e=1,t=js){super(e,ge);this.prefetchDelay=t}putLater(e,t,s){this.#e=setTimeout(()=>{t.perform(),this.put(e,t,s),this.#e=null},this.prefetchDelay)}put(e,t,s=Mt){super.put(e,t),this.#t[ge(e)]=new Date(new Date().getTime()+s)}clear(){if(super.clear(),this.#e)clearTimeout(this.#e)}evict(e){super.evict(e),delete this.#t[e]}has(e){if(super.has(e)){let t=this.#t[ge(e)];return t&&t>Date.now()}else return!1}}var Mt=1e4,X=new Ct,K={initialized:"initialized",requesting:"requesting",waiting:"waiting",receiving:"receiving",stopping:"stopping",stopped:"stopped"};class Ae{state=K.initialized;static confirmMethod(e){return Promise.resolve(confirm(e))}constructor(e,t,s,r=!1){let i=Ys(t,s),l=Qs(Xs(t,s),i),b=Gs(t,s),E=Zs(t,s);this.delegate=e,this.formElement=t,this.submitter=s,this.fetchRequest=new j(this,i,l,b,t,E),this.mustRedirect=r}get method(){return this.fetchRequest.method}set method(e){this.fetchRequest.method=e}get action(){return this.fetchRequest.url.toString()}set action(e){this.fetchRequest.url=M(e)}get body(){return this.fetchRequest.body}get enctype(){return this.fetchRequest.enctype}get isSafe(){return this.fetchRequest.isSafe}get location(){return this.fetchRequest.url}async start(){let{initialized:e,requesting:t}=K,s=be("data-turbo-confirm",this.submitter,this.formElement);if(typeof s==="string"){if(!await(typeof C.forms.confirm==="function"?C.forms.confirm:Ae.confirmMethod)(s,this.formElement,this.submitter))return}if(this.state==e)return this.state=t,this.fetchRequest.perform()}stop(){let{stopping:e,stopped:t}=K;if(this.state!=e&&this.state!=t)return this.state=e,this.fetchRequest.cancel(),!0}prepareRequest(e){if(!e.isSafe){let t=Js(we("csrf-param"))||we("csrf-token");if(t)e.headers["X-CSRF-Token"]=t}if(this.requestAcceptsTurboStreamResponse(e))e.acceptResponseType(G.contentType)}requestStarted(e){if(this.state=K.waiting,this.submitter)C.forms.submitter.beforeSubmit(this.submitter);this.setSubmitsWith(),ve(this.formElement),R("turbo:submit-start",{target:this.formElement,detail:{formSubmission:this}}),this.delegate.formSubmissionStarted(this)}requestPreventedHandlingResponse(e,t){X.clear(),this.result={success:t.succeeded,fetchResponse:t}}requestSucceededWithResponse(e,t){if(t.clientError||t.serverError){this.delegate.formSubmissionFailedWithResponse(this,t);return}if(X.clear(),this.requestMustRedirect(e)&&Ks(t)){let s=Error("Form responses must redirect to another location");this.delegate.formSubmissionErrored(this,s)}else this.state=K.receiving,this.result={success:!0,fetchResponse:t},this.delegate.formSubmissionSucceededWithResponse(this,t)}requestFailedWithResponse(e,t){this.result={success:!1,fetchResponse:t},this.delegate.formSubmissionFailedWithResponse(this,t)}requestErrored(e,t){this.result={success:!1,error:t},this.delegate.formSubmissionErrored(this,t)}requestFinished(e){if(this.state=K.stopped,this.submitter)C.forms.submitter.afterSubmit(this.submitter);this.resetSubmitterText(),Se(this.formElement),R("turbo:submit-end",{target:this.formElement,detail:{formSubmission:this,...this.result}}),this.delegate.formSubmissionFinished(this)}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")){let e=this.submitter;this.originalSubmitText=e.value,e.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")){let e=this.submitter;e.value=this.originalSubmitText}}requestMustRedirect(e){return!e.isSafe&&this.mustRedirect}requestAcceptsTurboStreamResponse(e){return!e.isSafe||ks("data-turbo-stream",this.submitter,this.formElement)}get submitsWith(){return this.submitter?.getAttribute("data-turbo-submits-with")}}function Gs(e,t){let s=new FormData(e),r=t?.getAttribute("name"),i=t?.getAttribute("value");if(r)s.append(r,i||"");return s}function Js(e){if(e!=null){let s=(document.cookie?document.cookie.split("; "):[]).find((r)=>r.startsWith(e));if(s){let r=s.split("=").slice(1).join("=");return r?decodeURIComponent(r):void 0}}}function Ks(e){return e.statusCode==200&&!e.redirected}function Xs(e,t){let s=typeof e.action==="string"?e.action:null;if(t?.hasAttribute("formaction"))return t.getAttribute("formaction")||"";else return e.getAttribute("action")||s||""}function Qs(e,t){let s=M(e);if(Ee(t))s.search="";return s}function Ys(e,t){let s=t?.getAttribute("formmethod")||e.getAttribute("method")||"";return ye(s.toLowerCase())||P.get}function Zs(e,t){return Tt(t?.getAttribute("formenctype")||e.enctype)}class ne{constructor(e){this.element=e}get activeElement(){return this.element.ownerDocument.activeElement}get children(){return[...this.element.children]}hasAnchor(e){return this.getElementForAnchor(e)!=null}getElementForAnchor(e){return e?this.element.querySelector(`[id='${e}'], a[name='${e}']`):null}get isConnected(){return this.element.isConnected}get firstAutofocusableElement(){return gt(this.element)}get permanentElements(){return kt(this.element)}getPermanentElementById(e){return Pt(this.element,e)}getPermanentElementMapForSnapshot(e){let t={};for(let s of this.permanentElements){let{id:r}=s,i=e.getPermanentElementById(r);if(i)t[r]=[s,i]}return t}}function Pt(e,t){return e.querySelector(`#${t}[data-turbo-permanent]`)}function kt(e){return e.querySelectorAll("[id][data-turbo-permanent]")}class Te{started=!1;constructor(e,t){this.delegate=e,this.eventTarget=t}start(){if(!this.started)this.eventTarget.addEventListener("submit",this.submitCaptured,!0),this.started=!0}stop(){if(this.started)this.eventTarget.removeEventListener("submit",this.submitCaptured,!0),this.started=!1}submitCaptured=()=>{this.eventTarget.removeEventListener("submit",this.submitBubbled,!1),this.eventTarget.addEventListener("submit",this.submitBubbled,!1)};submitBubbled=(e)=>{if(!e.defaultPrevented){let t=e.target instanceof HTMLFormElement?e.target:void 0,s=e.submitter||void 0;if(t&&er(t,s)&&tr(t,s)&&this.delegate.willSubmitForm(t,s))e.preventDefault(),e.stopImmediatePropagation(),this.delegate.formSubmitted(t,s)}}}function er(e,t){return(t?.getAttribute("formmethod")||e.getAttribute("method"))!="dialog"}function tr(e,t){let s=t?.getAttribute("formtarget")||e.getAttribute("target");return bt(s)}class xe{#e=(e)=>{};#t=(e)=>{};constructor(e,t){this.delegate=e,this.element=t}scrollToAnchor(e){let t=this.snapshot.getElementForAnchor(e);if(t)this.focusElement(t),this.scrollToElement(t);else this.scrollToPosition({x:0,y:0})}scrollToAnchorFromLocation(e){this.scrollToAnchor(se(e))}scrollToElement(e){e.scrollIntoView()}focusElement(e){if(e instanceof HTMLElement)if(e.hasAttribute("tabindex"))e.focus();else e.setAttribute("tabindex","-1"),e.focus(),e.removeAttribute("tabindex")}scrollToPosition({x:e,y:t}){this.scrollRoot.scrollTo(e,t)}scrollToTop(){this.scrollToPosition({x:0,y:0})}get scrollRoot(){return window}async render(e){let{isPreview:t,shouldRender:s,willRender:r,newSnapshot:i}=e,l=r;if(s)try{this.renderPromise=new Promise((H)=>this.#e=H),this.renderer=e,await this.prepareToRenderSnapshot(e);let b=new Promise((H)=>this.#t=H),E={resume:this.#t,render:this.renderer.renderElement,renderMethod:this.renderer.renderMethod};if(!this.delegate.allowsImmediateRender(i,E))await b;await this.renderSnapshot(e),this.delegate.viewRenderedSnapshot(i,t,this.renderer.renderMethod),this.delegate.preloadOnLoadLinksForView(this.element),this.finishRenderingSnapshot(e)}finally{delete this.renderer,this.#e(void 0),delete this.renderPromise}else if(l)this.invalidate(e.reloadReason)}invalidate(e){this.delegate.viewInvalidated(e)}async prepareToRenderSnapshot(e){this.markAsPreview(e.isPreview),await e.prepareToRender()}markAsPreview(e){if(e)this.element.setAttribute("data-turbo-preview","");else this.element.removeAttribute("data-turbo-preview")}markVisitDirection(e){this.element.setAttribute("data-turbo-visit-direction",e)}unmarkVisitDirection(){this.element.removeAttribute("data-turbo-visit-direction")}async renderSnapshot(e){await e.render()}finishRenderingSnapshot(e){e.finishRendering()}}class It extends xe{missing(){this.element.innerHTML='<strong class="turbo-frame-error">Content missing</strong>'}get snapshot(){return new ne(this.element)}}class Ve{constructor(e,t){this.delegate=e,this.element=t}start(){this.element.addEventListener("click",this.clickBubbled),document.addEventListener("turbo:click",this.linkClicked),document.addEventListener("turbo:before-visit",this.willVisit)}stop(){this.element.removeEventListener("click",this.clickBubbled),document.removeEventListener("turbo:click",this.linkClicked),document.removeEventListener("turbo:before-visit",this.willVisit)}clickBubbled=(e)=>{if(this.clickEventIsSignificant(e))this.clickEvent=e;else delete this.clickEvent};linkClicked=(e)=>{if(this.clickEvent&&this.clickEventIsSignificant(e)){if(this.delegate.shouldInterceptLinkClick(e.target,e.detail.url,e.detail.originalEvent))this.clickEvent.preventDefault(),e.preventDefault(),this.delegate.linkClickIntercepted(e.target,e.detail.url,e.detail.originalEvent)}delete this.clickEvent};willVisit=(e)=>{delete this.clickEvent};clickEventIsSignificant(e){let t=e.composed?e.target?.parentElement:e.target,s=vt(t)||t;return s instanceof Element&&s.closest("turbo-frame, html")==this.element}}class We{started=!1;constructor(e,t){this.delegate=e,this.eventTarget=t}start(){if(!this.started)this.eventTarget.addEventListener("click",this.clickCaptured,!0),this.started=!0}stop(){if(this.started)this.eventTarget.removeEventListener("click",this.clickCaptured,!0),this.started=!1}clickCaptured=()=>{this.eventTarget.removeEventListener("click",this.clickBubbled,!1),this.eventTarget.addEventListener("click",this.clickBubbled,!1)};clickBubbled=(e)=>{if(e instanceof MouseEvent&&this.clickEventIsSignificant(e)){let t=e.composedPath&&e.composedPath()[0]||e.target,s=vt(t);if(s&&bt(s.target)){let r=wt(s);if(this.delegate.willFollowLinkToLocation(s,r,e))e.preventDefault(),this.delegate.followedLinkToLocation(s,r)}}};clickEventIsSignificant(e){return!(e.target&&e.target.isContentEditable||e.defaultPrevented||e.which>1||e.altKey||e.ctrlKey||e.metaKey||e.shiftKey)}}class _e{constructor(e,t){this.delegate=e,this.linkInterceptor=new We(this,t)}start(){this.linkInterceptor.start()}stop(){this.linkInterceptor.stop()}canPrefetchRequestToLocation(e,t){return!1}prefetchAndCacheRequestToLocation(e,t){return}willFollowLinkToLocation(e,t,s){return this.delegate.willSubmitFormLinkToLocation(e,t,s)&&(e.hasAttribute("data-turbo-method")||e.hasAttribute("data-turbo-stream"))}followedLinkToLocation(e,t){let s=document.createElement("form"),r="hidden";for(let[ee,W]of t.searchParams)s.append(Object.assign(document.createElement("input"),{type:"hidden",name:ee,value:W}));let i=Object.assign(t,{search:""});s.setAttribute("data-turbo","true"),s.setAttribute("action",i.href),s.setAttribute("hidden","");let l=e.getAttribute("data-turbo-method");if(l)s.setAttribute("method",l);let b=e.getAttribute("data-turbo-frame");if(b)s.setAttribute("data-turbo-frame",b);let E=z(e);if(E)s.setAttribute("data-turbo-action",E);let q=e.getAttribute("data-turbo-confirm");if(q)s.setAttribute("data-turbo-confirm",q);if(e.hasAttribute("data-turbo-stream"))s.setAttribute("data-turbo-stream","");this.delegate.submittedFormLinkToLocation(e,t,s),document.body.appendChild(s),s.addEventListener("turbo:submit-end",()=>s.remove(),{once:!0}),requestAnimationFrame(()=>s.requestSubmit())}}class Ue{static async preservingPermanentElements(e,t,s){let r=new this(e,t);r.enter(),await s(),r.leave()}constructor(e,t){this.delegate=e,this.permanentElementMap=t}enter(){for(let e in this.permanentElementMap){let[t,s]=this.permanentElementMap[e];this.delegate.enteringBardo(t,s),this.replaceNewPermanentElementWithPlaceholder(s)}}leave(){for(let e in this.permanentElementMap){let[t]=this.permanentElementMap[e];this.replaceCurrentPermanentElementWithClone(t),this.replacePlaceholderWithPermanentElement(t),this.delegate.leavingBardo(t)}}replaceNewPermanentElementWithPlaceholder(e){let t=sr(e);e.replaceWith(t)}replaceCurrentPermanentElementWithClone(e){let t=e.cloneNode(!0);e.replaceWith(t)}replacePlaceholderWithPermanentElement(e){this.getPlaceholderById(e.id)?.replaceWith(e)}getPlaceholderById(e){return this.placeholders.find((t)=>t.content==e)}get placeholders(){return[...document.querySelectorAll("meta[name=turbo-permanent-placeholder][content]")]}}function sr(e){let t=document.createElement("meta");return t.setAttribute("name","turbo-permanent-placeholder"),t.setAttribute("content",e.id),t}class Re{#e=null;static renderElement(e,t){}constructor(e,t,s,r=!0){this.currentSnapshot=e,this.newSnapshot=t,this.isPreview=s,this.willRender=r,this.renderElement=this.constructor.renderElement,this.promise=new Promise((i,l)=>this.resolvingFunctions={resolve:i,reject:l})}get shouldRender(){return!0}get shouldAutofocus(){return!0}get reloadReason(){return}prepareToRender(){return}render(){}finishRendering(){if(this.resolvingFunctions)this.resolvingFunctions.resolve(),delete this.resolvingFunctions}async preservingPermanentElements(e){await Ue.preservingPermanentElements(this,this.permanentElementMap,e)}focusFirstAutofocusableElement(){if(this.shouldAutofocus){let e=this.connectedSnapshot.firstAutofocusableElement;if(e)e.focus()}}enteringBardo(e){if(this.#e)return;if(e.contains(this.currentSnapshot.activeElement))this.#e=this.currentSnapshot.activeElement}leavingBardo(e){if(e.contains(this.#e)&&this.#e instanceof HTMLElement)this.#e.focus(),this.#e=null}get connectedSnapshot(){return this.newSnapshot.isConnected?this.newSnapshot:this.currentSnapshot}get currentElement(){return this.currentSnapshot.element}get newElement(){return this.newSnapshot.element}get permanentElementMap(){return this.currentSnapshot.getPermanentElementMapForSnapshot(this.newSnapshot)}get renderMethod(){return"replace"}}class oe extends Re{static renderElement(e,t){let s=document.createRange();s.selectNodeContents(e),s.deleteContents();let r=t,i=r.ownerDocument?.createRange();if(i)i.selectNodeContents(r),e.appendChild(i.extractContents())}constructor(e,t,s,r,i,l=!0){super(t,s,r,i,l);this.delegate=e}get shouldRender(){return!0}async render(){await te(),this.preservingPermanentElements(()=>{this.loadFrameElement()}),this.scrollFrameIntoView(),await te(),this.focusFirstAutofocusableElement(),await te(),this.activateScriptElements()}loadFrameElement(){this.delegate.willRenderFrame(this.currentElement,this.newElement),this.renderElement(this.currentElement,this.newElement)}scrollFrameIntoView(){if(this.currentElement.autoscroll||this.newElement.autoscroll){let e=this.currentElement.firstElementChild,t=rr(this.currentElement.getAttribute("data-autoscroll-block"),"end"),s=ir(this.currentElement.getAttribute("data-autoscroll-behavior"),"auto");if(e)return e.scrollIntoView({block:t,behavior:s}),!0}return!1}activateScriptElements(){for(let e of this.newScriptElements){let t=re(e);e.replaceWith(t)}}get newScriptElements(){return this.currentElement.querySelectorAll("script")}}function rr(e,t){if(e=="end"||e=="start"||e=="center"||e=="nearest")return e;else return t}function ir(e,t){if(e=="auto"||e=="smooth")return e;else return t}var nr=function(){let e=()=>{},t={morphStyle:"outerHTML",callbacks:{beforeNodeAdded:e,afterNodeAdded:e,beforeNodeMorphed:e,afterNodeMorphed:e,beforeNodeRemoved:e,afterNodeRemoved:e,beforeAttributeUpdated:e},head:{style:"merge",shouldPreserve:(p)=>p.getAttribute("im-preserve")==="true",shouldReAppend:(p)=>p.getAttribute("im-re-append")==="true",shouldRemove:e,afterHeadMorphed:e},restoreFocus:!0};function s(p,T,v={}){p=ee(p);let S=W(T),w=H(p,S,v),d=i(w,()=>E(w,p,S,(a)=>{if(a.morphStyle==="innerHTML")return l(a,p,S),Array.from(p.childNodes);else return r(a,p,S)}));return w.pantry.remove(),d}function r(p,T,v){let S=W(T);return l(p,S,v,T,T.nextSibling),Array.from(S.childNodes)}function i(p,T){if(!p.config.restoreFocus)return T();let v=document.activeElement;if(!(v instanceof HTMLInputElement||v instanceof HTMLTextAreaElement))return T();let{id:S,selectionStart:w,selectionEnd:d}=v,a=T();if(S&&S!==document.activeElement?.getAttribute("id"))v=p.target.querySelector(`[id="${S}"]`),v?.focus();if(v&&!v.selectionEnd&&d)v.setSelectionRange(w,d);return a}let l=function(){function p(o,n,h,c=null,m=null){if(n instanceof HTMLTemplateElement&&h instanceof HTMLTemplateElement)n=n.content,h=h.content;c||=n.firstChild;for(let f of h.childNodes){if(c&&c!=m){let A=v(o,f,c,m);if(A){if(A!==c)w(o,c,A);b(A,f,o),c=A.nextSibling;continue}}if(f instanceof Element){let A=f.getAttribute("id");if(o.persistentIds.has(A)){let B=d(n,A,c,o);b(B,f,o),c=B.nextSibling;continue}}let g=T(n,f,c,o);if(g)c=g.nextSibling}while(c&&c!=m){let f=c;c=c.nextSibling,S(o,f)}}function T(o,n,h,c){if(c.callbacks.beforeNodeAdded(n)===!1)return null;if(c.idMap.has(n)){let m=document.createElement(n.tagName);return o.insertBefore(m,h),b(m,n,c),c.callbacks.afterNodeAdded(m),m}else{let m=document.importNode(n,!0);return o.insertBefore(m,h),c.callbacks.afterNodeAdded(m),m}}let v=function(){function o(c,m,f,g){let A=null,B=m.nextSibling,st=0,F=f;while(F&&F!=g){if(h(F,m)){if(n(c,F,m))return F;if(A===null){if(!c.idMap.has(F))A=F}}if(A===null&&B&&h(F,B)){if(st++,B=B.nextSibling,st>=2)A=void 0}if(c.activeElementAndParents.includes(F))break;F=F.nextSibling}return A||null}function n(c,m,f){let g=c.idMap.get(m),A=c.idMap.get(f);if(!A||!g)return!1;for(let B of g)if(A.has(B))return!0;return!1}function h(c,m){let f=c,g=m;return f.nodeType===g.nodeType&&f.tagName===g.tagName&&(!f.getAttribute?.("id")||f.getAttribute?.("id")===g.getAttribute?.("id"))}return o}();function S(o,n){if(o.idMap.has(n))u(o.pantry,n,null);else{if(o.callbacks.beforeNodeRemoved(n)===!1)return;n.parentNode?.removeChild(n),o.callbacks.afterNodeRemoved(n)}}function w(o,n,h){let c=n;while(c&&c!==h){let m=c;c=c.nextSibling,S(o,m)}return c}function d(o,n,h,c){let m=c.target.getAttribute?.("id")===n&&c.target||c.target.querySelector(`[id="${n}"]`)||c.pantry.querySelector(`[id="${n}"]`);return a(m,c),u(o,m,h),m}function a(o,n){let h=o.getAttribute("id");while(o=o.parentNode){let c=n.idMap.get(o);if(c){if(c.delete(h),!c.size)n.idMap.delete(o)}}}function u(o,n,h){if(o.moveBefore)try{o.moveBefore(n,h)}catch(c){o.insertBefore(n,h)}else o.insertBefore(n,h)}return p}(),b=function(){function p(a,u,o){if(o.ignoreActive&&a===document.activeElement)return null;if(o.callbacks.beforeNodeMorphed(a,u)===!1)return a;if(a instanceof HTMLHeadElement&&o.head.ignore);else if(a instanceof HTMLHeadElement&&o.head.style!=="morph")q(a,u,o);else if(T(a,u,o),!d(a,o))l(o,a,u);return o.callbacks.afterNodeMorphed(a,u),a}function T(a,u,o){let n=u.nodeType;if(n===1){let h=a,c=u,m=h.attributes,f=c.attributes;for(let g of f){if(w(g.name,h,"update",o))continue;if(h.getAttribute(g.name)!==g.value)h.setAttribute(g.name,g.value)}for(let g=m.length-1;0<=g;g--){let A=m[g];if(!A)continue;if(!c.hasAttribute(A.name)){if(w(A.name,h,"remove",o))continue;h.removeAttribute(A.name)}}if(!d(h,o))v(h,c,o)}if(n===8||n===3){if(a.nodeValue!==u.nodeValue)a.nodeValue=u.nodeValue}}function v(a,u,o){if(a instanceof HTMLInputElement&&u instanceof HTMLInputElement&&u.type!=="file"){let n=u.value,h=a.value;if(S(a,u,"checked",o),S(a,u,"disabled",o),!u.hasAttribute("value")){if(!w("value",a,"remove",o))a.value="",a.removeAttribute("value")}else if(h!==n){if(!w("value",a,"update",o))a.setAttribute("value",n),a.value=n}}else if(a instanceof HTMLOptionElement&&u instanceof HTMLOptionElement)S(a,u,"selected",o);else if(a instanceof HTMLTextAreaElement&&u instanceof HTMLTextAreaElement){let n=u.value,h=a.value;if(w("value",a,"update",o))return;if(n!==h)a.value=n;if(a.firstChild&&a.firstChild.nodeValue!==n)a.firstChild.nodeValue=n}}function S(a,u,o,n){let h=u[o],c=a[o];if(h!==c){let m=w(o,a,"update",n);if(!m)a[o]=u[o];if(h){if(!m)a.setAttribute(o,"")}else if(!w(o,a,"remove",n))a.removeAttribute(o)}}function w(a,u,o,n){if(a==="value"&&n.ignoreActiveValue&&u===document.activeElement)return!0;return n.callbacks.beforeAttributeUpdated(a,u,o)===!1}function d(a,u){return!!u.ignoreActiveValue&&a===document.activeElement&&a!==document.body}return p}();function E(p,T,v,S){if(p.head.block){let w=T.querySelector("head"),d=v.querySelector("head");if(w&&d){let a=q(w,d,p);return Promise.all(a).then(()=>{let u=Object.assign(p,{head:{block:!1,ignore:!0}});return S(u)})}}return S(p)}function q(p,T,v){let S=[],w=[],d=[],a=[],u=new Map;for(let n of T.children)u.set(n.outerHTML,n);for(let n of p.children){let h=u.has(n.outerHTML),c=v.head.shouldReAppend(n),m=v.head.shouldPreserve(n);if(h||m)if(c)w.push(n);else u.delete(n.outerHTML),d.push(n);else if(v.head.style==="append"){if(c)w.push(n),a.push(n)}else if(v.head.shouldRemove(n)!==!1)w.push(n)}a.push(...u.values());let o=[];for(let n of a){let h=document.createRange().createContextualFragment(n.outerHTML).firstChild;if(v.callbacks.beforeNodeAdded(h)!==!1){if("href"in h&&h.href||"src"in h&&h.src){let c,m=new Promise(function(f){c=f});h.addEventListener("load",function(){c()}),o.push(m)}p.appendChild(h),v.callbacks.afterNodeAdded(h),S.push(h)}}for(let n of w)if(v.callbacks.beforeNodeRemoved(n)!==!1)p.removeChild(n),v.callbacks.afterNodeRemoved(n);return v.head.afterHeadMorphed(p,{added:S,kept:d,removed:w}),o}let H=function(){function p(o,n,h){let{persistentIds:c,idMap:m}=a(o,n),f=T(h),g=f.morphStyle||"outerHTML";if(!["innerHTML","outerHTML"].includes(g))throw`Do not understand how to morph style ${g}`;return{target:o,newContent:n,config:f,morphStyle:g,ignoreActive:f.ignoreActive,ignoreActiveValue:f.ignoreActiveValue,restoreFocus:f.restoreFocus,idMap:m,persistentIds:c,pantry:v(),activeElementAndParents:S(o),callbacks:f.callbacks,head:f.head}}function T(o){let n=Object.assign({},t);return Object.assign(n,o),n.callbacks=Object.assign({},t.callbacks,o.callbacks),n.head=Object.assign({},t.head,o.head),n}function v(){let o=document.createElement("div");return o.hidden=!0,document.body.insertAdjacentElement("afterend",o),o}function S(o){let n=[],h=document.activeElement;if(h?.tagName!=="BODY"&&o.contains(h))while(h){if(n.push(h),h===o)break;h=h.parentElement}return n}function w(o){let n=Array.from(o.querySelectorAll("[id]"));if(o.getAttribute?.("id"))n.push(o);return n}function d(o,n,h,c){for(let m of c){let f=m.getAttribute("id");if(n.has(f)){let g=m;while(g){let A=o.get(g);if(A==null)A=new Set,o.set(g,A);if(A.add(f),g===h)break;g=g.parentElement}}}}function a(o,n){let h=w(o),c=w(n),m=u(h,c),f=new Map;d(f,m,o,h);let g=n.__idiomorphRoot||n;return d(f,m,g,c),{persistentIds:m,idMap:f}}function u(o,n){let h=new Set,c=new Map;for(let{id:f,tagName:g}of o)if(c.has(f))h.add(f);else c.set(f,g);let m=new Set;for(let{id:f,tagName:g}of n)if(m.has(f))h.add(f);else if(c.get(f)===g)m.add(f);for(let f of h)m.delete(f);return m}return p}(),{normalizeElement:ee,normalizeParent:W}=function(){let p=new WeakSet;function T(d){if(d instanceof Document)return d.documentElement;else return d}function v(d){if(d==null)return document.createElement("div");else if(typeof d==="string")return v(w(d));else if(p.has(d))return d;else if(d instanceof Node)if(d.parentNode)return new S(d);else{let a=document.createElement("div");return a.append(d),a}else{let a=document.createElement("div");for(let u of[...d])a.append(u);return a}}class S{constructor(d){this.originalNode=d,this.realParentNode=d.parentNode,this.previousSibling=d.previousSibling,this.nextSibling=d.nextSibling}get childNodes(){let d=[],a=this.previousSibling?this.previousSibling.nextSibling:this.realParentNode.firstChild;while(a&&a!=this.nextSibling)d.push(a),a=a.nextSibling;return d}querySelectorAll(d){return this.childNodes.reduce((a,u)=>{if(u instanceof Element){if(u.matches(d))a.push(u);let o=u.querySelectorAll(d);for(let n=0;n<o.length;n++)a.push(o[n])}return a},[])}insertBefore(d,a){return this.realParentNode.insertBefore(d,a)}moveBefore(d,a){return this.realParentNode.moveBefore(d,a)}get __idiomorphRoot(){return this.originalNode}}function w(d){let a=new DOMParser,u=d.replace(/<svg(\s[^>]*>|>)([\s\S]*?)<\/svg>/gim,"");if(u.match(/<\/html>/)||u.match(/<\/head>/)||u.match(/<\/body>/)){let o=a.parseFromString(d,"text/html");if(u.match(/<\/html>/))return p.add(o),o;else{let n=o.firstChild;if(n)p.add(n);return n}}else{let n=a.parseFromString("<body><template>"+d+"</template></body>","text/html").body.querySelector("template").content;return p.add(n),n}}return{normalizeElement:T,normalizeParent:v}}();return{morph:s,defaults:t}}();function ae(e,t,{callbacks:s,...r}={}){nr.morph(e,t,{...r,callbacks:new Ft(s)})}function Le(e,t,s={}){ae(e,t.childNodes,{...s,morphStyle:"innerHTML"})}function qt(e,t){return e instanceof k&&e.shouldReloadWithMorph&&(!t||or(e,t))&&!e.closest("[data-turbo-permanent]")}function or(e,t){return t instanceof Element&&t.nodeName==="TURBO-FRAME"&&e.id===t.id&&(!t.getAttribute("src")||yt(e.src,t.getAttribute("src")))}function Ht(e){return e.parentElement.closest("turbo-frame[src][refresh=morph]")}class Ft{#e;constructor({beforeNodeMorphed:e}={}){this.#e=e||(()=>!0)}beforeNodeAdded=(e)=>!(e.id&&e.hasAttribute("data-turbo-permanent")&&document.getElementById(e.id));beforeNodeMorphed=(e,t)=>{if(e instanceof Element)if(!e.hasAttribute("data-turbo-permanent")&&this.#e(e,t))return!R("turbo:before-morph-element",{cancelable:!0,target:e,detail:{currentElement:e,newElement:t}}).defaultPrevented;else return!1};beforeAttributeUpdated=(e,t,s)=>!R("turbo:before-morph-attribute",{cancelable:!0,target:t,detail:{attributeName:e,mutationType:s}}).defaultPrevented;beforeNodeRemoved=(e)=>this.beforeNodeMorphed(e);afterNodeMorphed=(e,t)=>{if(e instanceof Element)R("turbo:morph-element",{target:e,detail:{currentElement:e,newElement:t}})}}class $e extends oe{static renderElement(e,t){R("turbo:before-frame-morph",{target:e,detail:{currentElement:e,newElement:t}}),Le(e,t,{callbacks:{beforeNodeMorphed:(s,r)=>{if(qt(s,r)&&Ht(s)===e)return s.reload(),!1;return!0}}})}async preservingPermanentElements(e){return await e()}}class O{static animationDuration=300;static get defaultCSS(){return mt`
|
|
7
|
+
.turbo-progress-bar {
|
|
8
|
+
position: fixed;
|
|
9
|
+
display: block;
|
|
10
|
+
top: 0;
|
|
11
|
+
left: 0;
|
|
12
|
+
height: 3px;
|
|
13
|
+
background: #0076ff;
|
|
14
|
+
z-index: 2147483647;
|
|
15
|
+
transition:
|
|
16
|
+
width ${O.animationDuration}ms ease-out,
|
|
17
|
+
opacity ${O.animationDuration/2}ms ${O.animationDuration/2}ms ease-in;
|
|
18
|
+
transform: translate3d(0, 0, 0);
|
|
19
|
+
}
|
|
20
|
+
`}hiding=!1;value=0;visible=!1;constructor(){this.stylesheetElement=this.createStylesheetElement(),this.progressElement=this.createProgressElement(),this.installStylesheetElement(),this.setValue(0)}show(){if(!this.visible)this.visible=!0,this.installProgressElement(),this.startTrickling()}hide(){if(this.visible&&!this.hiding)this.hiding=!0,this.fadeProgressElement(()=>{this.uninstallProgressElement(),this.stopTrickling(),this.visible=!1,this.hiding=!1})}setValue(e){this.value=e,this.refresh()}installStylesheetElement(){document.head.insertBefore(this.stylesheetElement,document.head.firstChild)}installProgressElement(){this.progressElement.style.width="0",this.progressElement.style.opacity="1",document.documentElement.insertBefore(this.progressElement,document.body),this.refresh()}fadeProgressElement(e){this.progressElement.style.opacity="0",setTimeout(e,O.animationDuration*1.5)}uninstallProgressElement(){if(this.progressElement.parentNode)document.documentElement.removeChild(this.progressElement)}startTrickling(){if(!this.trickleInterval)this.trickleInterval=window.setInterval(this.trickle,O.animationDuration)}stopTrickling(){window.clearInterval(this.trickleInterval),delete this.trickleInterval}trickle=()=>{this.setValue(this.value+Math.random()/100)};refresh(){requestAnimationFrame(()=>{this.progressElement.style.width=`${10+this.value*90}%`})}createStylesheetElement(){let e=document.createElement("style");e.type="text/css",e.textContent=O.defaultCSS;let t=pt();if(t)e.nonce=t;return e}createProgressElement(){let e=document.createElement("div");return e.className="turbo-progress-bar",e}}class Bt extends ne{detailsByOuterHTML=this.children.filter((e)=>!hr(e)).map((e)=>mr(e)).reduce((e,t)=>{let{outerHTML:s}=t,r=s in e?e[s]:{type:ar(t),tracked:cr(t),elements:[]};return{...e,[s]:{...r,elements:[...r.elements,t]}}},{});get trackedElementSignature(){return Object.keys(this.detailsByOuterHTML).filter((e)=>this.detailsByOuterHTML[e].tracked).join("")}getScriptElementsNotInSnapshot(e){return this.getElementsMatchingTypeNotInSnapshot("script",e)}getStylesheetElementsNotInSnapshot(e){return this.getElementsMatchingTypeNotInSnapshot("stylesheet",e)}getElementsMatchingTypeNotInSnapshot(e,t){return Object.keys(this.detailsByOuterHTML).filter((s)=>!(s in t.detailsByOuterHTML)).map((s)=>this.detailsByOuterHTML[s]).filter(({type:s})=>s==e).map(({elements:[s]})=>s)}get provisionalElements(){return Object.keys(this.detailsByOuterHTML).reduce((e,t)=>{let{type:s,tracked:r,elements:i}=this.detailsByOuterHTML[t];if(s==null&&!r)return[...e,...i];else if(i.length>1)return[...e,...i.slice(1)];else return e},[])}getMetaValue(e){let t=this.findMetaElementByName(e);return t?t.getAttribute("content"):null}findMetaElementByName(e){return Object.keys(this.detailsByOuterHTML).reduce((t,s)=>{let{elements:[r]}=this.detailsByOuterHTML[s];return dr(r,e)?r:t},void 0|void 0)}}function ar(e){if(lr(e))return"script";else if(ur(e))return"stylesheet"}function cr(e){return e.getAttribute("data-turbo-track")=="reload"}function lr(e){return e.localName=="script"}function hr(e){return e.localName=="noscript"}function ur(e){let t=e.localName;return t=="style"||t=="link"&&e.getAttribute("rel")=="stylesheet"}function dr(e,t){return e.localName=="meta"&&e.getAttribute("name")==t}function mr(e){if(e.hasAttribute("nonce"))e.setAttribute("nonce","");return e}class I extends ne{static fromHTMLString(e=""){return this.fromDocument(dt(e))}static fromElement(e){return this.fromDocument(e.ownerDocument)}static fromDocument({documentElement:e,body:t,head:s}){return new this(e,t,new Bt(s))}constructor(e,t,s){super(t);this.documentElement=e,this.headSnapshot=s}clone(){let e=this.element.cloneNode(!0),t=this.element.querySelectorAll("select"),s=e.querySelectorAll("select");for(let[r,i]of t.entries()){let l=s[r];for(let b of l.selectedOptions)b.selected=!1;for(let b of i.selectedOptions)l.options[b.index].selected=!0}for(let r of e.querySelectorAll('input[type="password"]'))r.value="";for(let r of e.querySelectorAll("noscript"))r.remove();return new I(this.documentElement,e,this.headSnapshot)}get lang(){return this.documentElement.getAttribute("lang")}get dir(){return this.documentElement.getAttribute("dir")}get headElement(){return this.headSnapshot.element}get rootLocation(){let e=this.getSetting("root")??"/";return M(e)}get cacheControlValue(){return this.getSetting("cache-control")}get isPreviewable(){return this.cacheControlValue!="no-preview"}get isCacheable(){return this.cacheControlValue!="no-cache"}get isVisitable(){return this.getSetting("visit-control")!="reload"}get prefersViewTransitions(){return(this.getSetting("view-transition")==="true"||this.headSnapshot.getMetaValue("view-transition")==="same-origin")&&!window.matchMedia("(prefers-reduced-motion: reduce)").matches}get refreshMethod(){return this.getSetting("refresh-method")}get refreshScroll(){return this.getSetting("refresh-scroll")}getSetting(e){return this.headSnapshot.getMetaValue(`turbo-${e}`)}}class Dt{#e=!1;#t=Promise.resolve();renderChange(e,t){if(e&&this.viewTransitionsAvailable&&!this.#e)this.#e=!0,this.#t=this.#t.then(async()=>{await document.startViewTransition(t).finished});else this.#t=this.#t.then(t);return this.#t}get viewTransitionsAvailable(){return document.startViewTransition}}var fr={action:"advance",historyChanged:!1,visitCachedSnapshot:()=>{},willRender:!0,updateHistory:!0,shouldCacheSnapshot:!0,acceptsStreamResponse:!1,refresh:{}},pe={visitStart:"visitStart",requestStart:"requestStart",requestEnd:"requestEnd",visitEnd:"visitEnd"},D={initialized:"initialized",started:"started",canceled:"canceled",failed:"failed",completed:"completed"},Y={networkFailure:0,timeoutFailure:-1,contentTypeMismatch:-2},pr={advance:"forward",restore:"back",replace:"none"};class Ot{identifier=V();timingMetrics={};followedRedirect=!1;historyChanged=!1;scrolled=!1;shouldCacheSnapshot=!0;acceptsStreamResponse=!1;snapshotCached=!1;state=D.initialized;viewTransitioner=new Dt;constructor(e,t,s,r={}){this.delegate=e,this.location=t,this.restorationIdentifier=s||V();let{action:i,historyChanged:l,referrer:b,snapshot:E,snapshotHTML:q,response:H,visitCachedSnapshot:ee,willRender:W,updateHistory:p,shouldCacheSnapshot:T,acceptsStreamResponse:v,direction:S,refresh:w}={...fr,...r};this.action=i,this.historyChanged=l,this.referrer=b,this.snapshot=E,this.snapshotHTML=q,this.response=H,this.isPageRefresh=this.view.isPageRefresh(this),this.visitCachedSnapshot=ee,this.willRender=W,this.updateHistory=p,this.scrolled=!W,this.shouldCacheSnapshot=T,this.acceptsStreamResponse=v,this.direction=S||pr[i],this.refresh=w}get adapter(){return this.delegate.adapter}get view(){return this.delegate.view}get history(){return this.delegate.history}get restorationData(){return this.history.getRestorationDataForIdentifier(this.restorationIdentifier)}start(){if(this.state==D.initialized)this.recordTimingMetric(pe.visitStart),this.state=D.started,this.adapter.visitStarted(this),this.delegate.visitStarted(this)}cancel(){if(this.state==D.started){if(this.request)this.request.cancel();this.cancelRender(),this.state=D.canceled}}complete(){if(this.state==D.started){if(this.recordTimingMetric(pe.visitEnd),this.adapter.visitCompleted(this),this.state=D.completed,this.followRedirect(),!this.followedRedirect)this.delegate.visitCompleted(this)}}fail(){if(this.state==D.started)this.state=D.failed,this.adapter.visitFailed(this),this.delegate.visitCompleted(this)}changeHistory(){if(!this.historyChanged&&this.updateHistory){let e=this.location.href===this.referrer?.href?"replace":this.action,t=ft(e);this.history.update(t,this.location,this.restorationIdentifier),this.historyChanged=!0}}issueRequest(){if(this.hasPreloadedResponse())this.simulateRequest();else if(this.shouldIssueRequest()&&!this.request)this.request=new j(this,P.get,this.location),this.request.perform()}simulateRequest(){if(this.response)this.startRequest(),this.recordResponse(),this.finishRequest()}startRequest(){this.recordTimingMetric(pe.requestStart),this.adapter.visitRequestStarted(this)}recordResponse(e=this.response){if(this.response=e,e){let{statusCode:t}=e;if(at(t))this.adapter.visitRequestCompleted(this);else this.adapter.visitRequestFailedWithStatusCode(this,t)}}finishRequest(){this.recordTimingMetric(pe.requestEnd),this.adapter.visitRequestFinished(this)}loadResponse(){if(this.response){let{statusCode:e,responseHTML:t}=this.response;this.render(async()=>{if(this.shouldCacheSnapshot)this.cacheSnapshot();if(this.view.renderPromise)await this.view.renderPromise;if(at(e)&&t!=null){let s=I.fromHTMLString(t);await this.renderPageSnapshot(s,!1),this.adapter.visitRendered(this),this.complete()}else await this.view.renderError(I.fromHTMLString(t),this),this.adapter.visitRendered(this),this.fail()})}}getCachedSnapshot(){let e=this.view.getCachedSnapshotForLocation(this.location)||this.getPreloadedSnapshot();if(e&&(!se(this.location)||e.hasAnchor(se(this.location)))){if(this.action=="restore"||e.isPreviewable)return e}}getPreloadedSnapshot(){if(this.snapshotHTML)return I.fromHTMLString(this.snapshotHTML)}hasCachedSnapshot(){return this.getCachedSnapshot()!=null}loadCachedSnapshot(){let e=this.getCachedSnapshot();if(e){let t=this.shouldIssueRequest();this.render(async()=>{if(this.cacheSnapshot(),this.isPageRefresh)this.adapter.visitRendered(this);else{if(this.view.renderPromise)await this.view.renderPromise;if(await this.renderPageSnapshot(e,t),this.adapter.visitRendered(this),!t)this.complete()}})}}followRedirect(){if(this.redirectedToLocation&&!this.followedRedirect&&this.response?.redirected)this.adapter.visitProposedToLocation(this.redirectedToLocation,{action:"replace",response:this.response,shouldCacheSnapshot:!1,willRender:!1}),this.followedRedirect=!0}prepareRequest(e){if(this.acceptsStreamResponse)e.acceptResponseType(G.contentType)}requestStarted(){this.startRequest()}requestPreventedHandlingResponse(e,t){}async requestSucceededWithResponse(e,t){let s=await t.responseHTML,{redirected:r,statusCode:i}=t;if(s==null)this.recordResponse({statusCode:Y.contentTypeMismatch,redirected:r});else this.redirectedToLocation=t.redirected?t.location:void 0,this.recordResponse({statusCode:i,responseHTML:s,redirected:r})}async requestFailedWithResponse(e,t){let s=await t.responseHTML,{redirected:r,statusCode:i}=t;if(s==null)this.recordResponse({statusCode:Y.contentTypeMismatch,redirected:r});else this.recordResponse({statusCode:i,responseHTML:s,redirected:r})}requestErrored(e,t){this.recordResponse({statusCode:Y.networkFailure,redirected:!1})}requestFinished(){this.finishRequest()}performScroll(){if(!this.scrolled&&!this.view.forceReloaded&&!this.view.shouldPreserveScrollPosition(this)){if(this.action=="restore")this.scrollToRestoredPosition()||this.scrollToAnchor()||this.view.scrollToTop();else this.scrollToAnchor()||this.view.scrollToTop();this.scrolled=!0}}scrollToRestoredPosition(){let{scrollPosition:e}=this.restorationData;if(e)return this.view.scrollToPosition(e),!0}scrollToAnchor(){let e=se(this.location);if(e!=null)return this.view.scrollToAnchor(e),!0}recordTimingMetric(e){this.timingMetrics[e]=new Date().getTime()}getTimingMetrics(){return{...this.timingMetrics}}hasPreloadedResponse(){return typeof this.response=="object"}shouldIssueRequest(){if(this.action=="restore")return!this.hasCachedSnapshot();else return this.willRender}cacheSnapshot(){if(!this.snapshotCached)this.view.cacheSnapshot(this.snapshot).then((e)=>e&&this.visitCachedSnapshot(e)),this.snapshotCached=!0}async render(e){this.cancelRender(),await new Promise((t)=>{this.frame=document.visibilityState==="hidden"?setTimeout(()=>t(),0):requestAnimationFrame(()=>t())}),await e(),delete this.frame}async renderPageSnapshot(e,t){await this.viewTransitioner.renderChange(this.view.shouldTransitionTo(e),async()=>{await this.view.renderPage(e,t,this.willRender,this),this.performScroll()})}cancelRender(){if(this.frame)cancelAnimationFrame(this.frame),delete this.frame}}function at(e){return e>=200&&e<300}class Nt{progressBar=new O;constructor(e){this.session=e}visitProposedToLocation(e,t){if(N(e,this.navigator.rootLocation))this.navigator.startVisit(e,t?.restorationIdentifier||V(),t);else window.location.href=e.toString()}visitStarted(e){this.location=e.location,this.redirectedToLocation=null,e.loadCachedSnapshot(),e.issueRequest()}visitRequestStarted(e){if(this.progressBar.setValue(0),e.hasCachedSnapshot()||e.action!="restore")this.showVisitProgressBarAfterDelay();else this.showProgressBar()}visitRequestCompleted(e){if(e.loadResponse(),e.response.redirected)this.redirectedToLocation=e.redirectedToLocation}visitRequestFailedWithStatusCode(e,t){switch(t){case Y.networkFailure:case Y.timeoutFailure:case Y.contentTypeMismatch:return this.reload({reason:"request_failed",context:{statusCode:t}});default:return e.loadResponse()}}visitRequestFinished(e){}visitCompleted(e){this.progressBar.setValue(1),this.hideVisitProgressBar()}pageInvalidated(e){this.reload(e)}visitFailed(e){this.progressBar.setValue(1),this.hideVisitProgressBar()}visitRendered(e){}linkPrefetchingIsEnabledForLocation(e){return!0}formSubmissionStarted(e){this.progressBar.setValue(0),this.showFormProgressBarAfterDelay()}formSubmissionFinished(e){this.progressBar.setValue(1),this.hideFormProgressBar()}showVisitProgressBarAfterDelay(){this.visitProgressBarTimeout=window.setTimeout(this.showProgressBar,this.session.progressBarDelay)}hideVisitProgressBar(){if(this.progressBar.hide(),this.visitProgressBarTimeout!=null)window.clearTimeout(this.visitProgressBarTimeout),delete this.visitProgressBarTimeout}showFormProgressBarAfterDelay(){if(this.formProgressBarTimeout==null)this.formProgressBarTimeout=window.setTimeout(this.showProgressBar,this.session.progressBarDelay)}hideFormProgressBar(){if(this.progressBar.hide(),this.formProgressBarTimeout!=null)window.clearTimeout(this.formProgressBarTimeout),delete this.formProgressBarTimeout}showProgressBar=()=>{this.progressBar.show()};reload(e){R("turbo:reload",{detail:e}),window.location.href=(this.redirectedToLocation||this.location)?.toString()||window.location.href}get navigator(){return this.session.navigator}}class xt{selector="[data-turbo-temporary]";started=!1;start(){if(!this.started)this.started=!0,addEventListener("turbo:before-cache",this.removeTemporaryElements,!1)}stop(){if(this.started)this.started=!1,removeEventListener("turbo:before-cache",this.removeTemporaryElements,!1)}removeTemporaryElements=(e)=>{for(let t of this.temporaryElements)t.remove()};get temporaryElements(){return[...document.querySelectorAll(this.selector)]}}class Vt{constructor(e,t){this.session=e,this.element=t,this.linkInterceptor=new Ve(this,t),this.formSubmitObserver=new Te(this,t)}start(){this.linkInterceptor.start(),this.formSubmitObserver.start()}stop(){this.linkInterceptor.stop(),this.formSubmitObserver.stop()}shouldInterceptLinkClick(e,t,s){return this.#t(e)}linkClickIntercepted(e,t,s){let r=this.#s(e);if(r)r.delegate.linkClickIntercepted(e,t,s)}willSubmitForm(e,t){return e.closest("turbo-frame")==null&&this.#e(e,t)&&this.#t(e,t)}formSubmitted(e,t){let s=this.#s(e,t);if(s)s.delegate.formSubmitted(e,t)}#e(e,t){let s=De(e,t),r=this.element.ownerDocument.querySelector('meta[name="turbo-root"]'),i=M(r?.content??"/");return this.#t(e,t)&&N(s,i)}#t(e,t){if(e instanceof HTMLFormElement?this.session.submissionIsNavigatable(e,t):this.session.elementIsNavigatable(e)){let r=this.#s(e,t);return r?r!=e.closest("turbo-frame"):!1}else return!1}#s(e,t){let s=t?.getAttribute("data-turbo-frame")||e.getAttribute("data-turbo-frame");if(s&&s!="_top"){let r=this.element.querySelector(`#${s}:not([disabled])`);if(r instanceof k)return r}}}class Wt{location;restorationIdentifier=V();restorationData={};started=!1;currentIndex=0;constructor(e){this.delegate=e}start(){if(!this.started)addEventListener("popstate",this.onPopState,!1),this.currentIndex=history.state?.turbo?.restorationIndex||0,this.started=!0,this.replace(new URL(window.location.href))}stop(){if(this.started)removeEventListener("popstate",this.onPopState,!1),this.started=!1}push(e,t){this.update(history.pushState,e,t)}replace(e,t){this.update(history.replaceState,e,t)}update(e,t,s=V()){if(e===history.pushState)++this.currentIndex;let r={turbo:{restorationIdentifier:s,restorationIndex:this.currentIndex}};e.call(history,r,"",t.href),this.location=t,this.restorationIdentifier=s}getRestorationDataForIdentifier(e){return this.restorationData[e]||{}}updateRestorationData(e){let{restorationIdentifier:t}=this,s=this.restorationData[t];this.restorationData[t]={...s,...e}}assumeControlOfScrollRestoration(){if(!this.previousScrollRestoration)this.previousScrollRestoration=history.scrollRestoration??"auto",history.scrollRestoration="manual"}relinquishControlOfScrollRestoration(){if(this.previousScrollRestoration)history.scrollRestoration=this.previousScrollRestoration,delete this.previousScrollRestoration}onPopState=(e)=>{let{turbo:t}=e.state||{};if(this.location=new URL(window.location.href),t){let{restorationIdentifier:s,restorationIndex:r}=t;this.restorationIdentifier=s;let i=r>this.currentIndex?"forward":"back";this.delegate.historyPoppedToLocationWithRestorationIdentifierAndDirection(this.location,s,i),this.currentIndex=r}else this.currentIndex++,this.delegate.historyPoppedWithEmptyState(this.location)}}class _t{started=!1;#e=null;constructor(e,t){this.delegate=e,this.eventTarget=t}start(){if(this.started)return;if(this.eventTarget.readyState==="loading")this.eventTarget.addEventListener("DOMContentLoaded",this.#t,{once:!0});else this.#t()}stop(){if(!this.started)return;this.eventTarget.removeEventListener("mouseenter",this.#s,{capture:!0,passive:!0}),this.eventTarget.removeEventListener("mouseleave",this.#o,{capture:!0,passive:!0}),this.eventTarget.removeEventListener("turbo:before-fetch-request",this.#i,!0),this.started=!1}#t=()=>{this.eventTarget.addEventListener("mouseenter",this.#s,{capture:!0,passive:!0}),this.eventTarget.addEventListener("mouseleave",this.#o,{capture:!0,passive:!0}),this.eventTarget.addEventListener("turbo:before-fetch-request",this.#i,!0),this.started=!0};#s=(e)=>{if(we("turbo-prefetch")==="false")return;let t=e.target;if(t.matches&&t.matches("a[href]:not([target^=_]):not([download])")&&this.#c(t)){let r=t,i=wt(r);if(this.delegate.canPrefetchRequestToLocation(r,i)){this.#e=r;let l=new j(this,P.get,i,new URLSearchParams,t);l.fetchOptions.priority="low",X.putLater(i,l,this.#r)}}};#o=(e)=>{if(e.target===this.#e)this.#a()};#a=()=>{X.clear(),this.#e=null};#i=(e)=>{if(e.target.tagName!=="FORM"&&e.detail.fetchOptions.method==="GET"){let t=X.get(e.detail.url);if(t)e.detail.fetchRequest=t;X.clear()}};prepareRequest(e){let t=e.target;e.headers["X-Sec-Purpose"]="prefetch";let s=t.closest("turbo-frame"),r=t.getAttribute("data-turbo-frame")||s?.getAttribute("target")||s?.id;if(r&&r!=="_top")e.headers["Turbo-Frame"]=r}requestSucceededWithResponse(){}requestStarted(e){}requestErrored(e){}requestFinished(e){}requestPreventedHandlingResponse(e,t){}requestFailedWithResponse(e,t){}get#r(){return Number(we("turbo-prefetch-cache-time"))||Mt}#c(e){if(!e.getAttribute("href"))return!1;if(gr(e))return!1;if(br(e))return!1;if(vr(e))return!1;if(Sr(e))return!1;if(yr(e))return!1;return!0}}var gr=(e)=>e.origin!==document.location.origin||!["http:","https:"].includes(e.protocol)||e.hasAttribute("target"),br=(e)=>e.pathname+e.search===document.location.pathname+document.location.search||e.href.startsWith("#"),vr=(e)=>{if(e.getAttribute("data-turbo-prefetch")==="false")return!0;if(e.getAttribute("data-turbo")==="false")return!0;let t=Q(e,"[data-turbo-prefetch]");if(t&&t.getAttribute("data-turbo-prefetch")==="false")return!0;return!1},Sr=(e)=>{let t=e.getAttribute("data-turbo-method");if(t&&t.toLowerCase()!=="get")return!0;if(wr(e))return!0;if(e.hasAttribute("data-turbo-confirm"))return!0;if(e.hasAttribute("data-turbo-stream"))return!0;return!1},wr=(e)=>e.hasAttribute("data-remote")||e.hasAttribute("data-behavior")||e.hasAttribute("data-confirm")||e.hasAttribute("data-method"),yr=(e)=>R("turbo:before-prefetch",{target:e,cancelable:!0}).defaultPrevented;class Ut{constructor(e){this.delegate=e}proposeVisit(e,t={}){if(this.delegate.allowsVisitingLocationWithAction(e,t.action))this.delegate.visitProposedToLocation(e,t)}startVisit(e,t,s={}){this.stop(),this.currentVisit=new Ot(this,M(e),t,{referrer:this.location,...s}),this.currentVisit.start()}submitForm(e,t){this.stop(),this.formSubmission=new Ae(this,e,t,!0),this.formSubmission.start()}stop(){if(this.formSubmission)this.formSubmission.stop(),delete this.formSubmission;if(this.currentVisit)this.currentVisit.cancel(),delete this.currentVisit}get adapter(){return this.delegate.adapter}get view(){return this.delegate.view}get rootLocation(){return this.view.snapshot.rootLocation}get history(){return this.delegate.history}formSubmissionStarted(e){if(typeof this.adapter.formSubmissionStarted==="function")this.adapter.formSubmissionStarted(e)}async formSubmissionSucceededWithResponse(e,t){if(e==this.formSubmission){let s=await t.responseHTML;if(s){let r=e.isSafe;if(!r)this.view.clearSnapshotCache();let{statusCode:i,redirected:l}=t,E={action:this.#e(e,t),shouldCacheSnapshot:r,response:{statusCode:i,responseHTML:s,redirected:l}};this.proposeVisit(t.location,E)}}}async formSubmissionFailedWithResponse(e,t){let s=await t.responseHTML;if(s){let r=I.fromHTMLString(s);if(t.serverError)await this.view.renderError(r,this.currentVisit);else await this.view.renderPage(r,!1,!0,this.currentVisit);if(r.refreshScroll!=="preserve")this.view.scrollToTop();this.view.clearSnapshotCache()}}formSubmissionErrored(e,t){console.error(t)}formSubmissionFinished(e){if(typeof this.adapter.formSubmissionFinished==="function")this.adapter.formSubmissionFinished(e)}linkPrefetchingIsEnabledForLocation(e){if(typeof this.adapter.linkPrefetchingIsEnabledForLocation==="function")return this.adapter.linkPrefetchingIsEnabledForLocation(e);return!0}visitStarted(e){this.delegate.visitStarted(e)}visitCompleted(e){this.delegate.visitCompleted(e),delete this.currentVisit}locationWithActionIsSamePage(e,t){return!1}get location(){return this.history.location}get restorationIdentifier(){return this.history.restorationIdentifier}#e(e,t){let{submitter:s,formElement:r}=e;return z(s,r)||this.#t(t)}#t(e){return e.redirected&&e.location.href===this.location?.href?"replace":"advance"}}var _={initial:0,loading:1,interactive:2,complete:3};class $t{stage=_.initial;started=!1;constructor(e){this.delegate=e}start(){if(!this.started){if(this.stage==_.initial)this.stage=_.loading;document.addEventListener("readystatechange",this.interpretReadyState,!1),addEventListener("pagehide",this.pageWillUnload,!1),this.started=!0}}stop(){if(this.started)document.removeEventListener("readystatechange",this.interpretReadyState,!1),removeEventListener("pagehide",this.pageWillUnload,!1),this.started=!1}interpretReadyState=()=>{let{readyState:e}=this;if(e=="interactive")this.pageIsInteractive();else if(e=="complete")this.pageIsComplete()};pageIsInteractive(){if(this.stage==_.loading)this.stage=_.interactive,this.delegate.pageBecameInteractive()}pageIsComplete(){if(this.pageIsInteractive(),this.stage==_.interactive)this.stage=_.complete,this.delegate.pageLoaded()}pageWillUnload=()=>{this.delegate.pageWillUnload()};get readyState(){return document.readyState}}class zt{started=!1;constructor(e){this.delegate=e}start(){if(!this.started)addEventListener("scroll",this.onScroll,!1),this.onScroll(),this.started=!0}stop(){if(this.started)removeEventListener("scroll",this.onScroll,!1),this.started=!1}onScroll=()=>{this.updatePosition({x:window.pageXOffset,y:window.pageYOffset})};updatePosition(e){this.delegate.scrollPositionChanged(e)}}class jt{render({fragment:e}){Ue.preservingPermanentElements(this,Er(e),()=>{Ar(e,()=>{Tr(()=>{document.documentElement.appendChild(e)})})})}enteringBardo(e,t){t.replaceWith(e.cloneNode(!0))}leavingBardo(){}}function Er(e){let t=kt(document.documentElement),s={};for(let r of t){let{id:i}=r;for(let l of e.querySelectorAll("turbo-stream")){let b=Pt(l.templateElement.content,i);if(b)s[i]=[r,b]}}return s}async function Ar(e,t){let s=`turbo-stream-autofocus-${V()}`,r=e.querySelectorAll("turbo-stream"),i=Rr(r),l=null;if(i){if(i.id)l=i.id;else l=s;i.id=l}if(t(),await te(),(document.activeElement==null||document.activeElement==document.body)&&l){let E=document.getElementById(l);if(Be(E))E.focus();if(E&&E.id==s)E.removeAttribute("id")}}async function Tr(e){let[t,s]=await Fs(e,()=>document.activeElement),r=t&&t.id;if(r){let i=document.getElementById(r);if(Be(i)&&i!=s)i.focus()}}function Rr(e){for(let t of e){let s=gt(t.templateElement.content);if(s)return s}return null}class Gt{sources=new Set;#e=!1;constructor(e){this.delegate=e}start(){if(!this.#e)this.#e=!0,addEventListener("turbo:before-fetch-response",this.inspectFetchResponse,!1)}stop(){if(this.#e)this.#e=!1,removeEventListener("turbo:before-fetch-response",this.inspectFetchResponse,!1)}connectStreamSource(e){if(!this.streamSourceIsConnected(e))this.sources.add(e),e.addEventListener("message",this.receiveMessageEvent,!1)}disconnectStreamSource(e){if(this.streamSourceIsConnected(e))this.sources.delete(e),e.removeEventListener("message",this.receiveMessageEvent,!1)}streamSourceIsConnected(e){return this.sources.has(e)}inspectFetchResponse=(e)=>{let t=Lr(e);if(t&&Cr(t))e.preventDefault(),this.receiveMessageResponse(t)};receiveMessageEvent=(e)=>{if(this.#e&&typeof e.data=="string")this.receiveMessageHTML(e.data)};async receiveMessageResponse(e){let t=await e.responseHTML;if(t)this.receiveMessageHTML(t)}receiveMessageHTML(e){this.delegate.receivedMessageFromStream(G.wrap(e))}}function Lr(e){let t=e.detail?.fetchResponse;if(t instanceof ie)return t}function Cr(e){return(e.contentType??"").startsWith(G.contentType)}class Jt extends Re{static renderElement(e,t){let{documentElement:s,body:r}=document;s.replaceChild(t,r)}async render(){this.replaceHeadAndBody(),this.activateScriptElements()}replaceHeadAndBody(){let{documentElement:e,head:t}=document;e.replaceChild(this.newHead,t),this.renderElement(this.currentElement,this.newElement)}activateScriptElements(){for(let e of this.scriptElements){let t=e.parentNode;if(t){let s=re(e);t.replaceChild(s,e)}}}get newHead(){return this.newSnapshot.headSnapshot.element}get scriptElements(){return document.documentElement.querySelectorAll("script")}}class ce extends Re{static renderElement(e,t){if(document.body&&t instanceof HTMLBodyElement)document.body.replaceWith(t);else document.documentElement.appendChild(t)}get shouldRender(){return this.newSnapshot.isVisitable&&this.trackedElementsAreIdentical}get reloadReason(){if(!this.newSnapshot.isVisitable)return{reason:"turbo_visit_control_is_reload"};if(!this.trackedElementsAreIdentical)return{reason:"tracked_element_mismatch"}}async prepareToRender(){this.#e(),await this.mergeHead()}async render(){if(this.willRender)await this.replaceBody()}finishRendering(){if(super.finishRendering(),!this.isPreview)this.focusFirstAutofocusableElement()}get currentHeadSnapshot(){return this.currentSnapshot.headSnapshot}get newHeadSnapshot(){return this.newSnapshot.headSnapshot}get newElement(){return this.newSnapshot.element}#e(){let{documentElement:e}=this.currentSnapshot,{dir:t,lang:s}=this.newSnapshot;if(s)e.setAttribute("lang",s);else e.removeAttribute("lang");if(t)e.setAttribute("dir",t);else e.removeAttribute("dir")}async mergeHead(){let e=this.mergeProvisionalElements(),t=this.copyNewHeadStylesheetElements();if(this.copyNewHeadScriptElements(),await e,await t,this.willRender)this.removeUnusedDynamicStylesheetElements()}async replaceBody(){await this.preservingPermanentElements(async()=>{this.activateNewBody(),await this.assignNewBody()})}get trackedElementsAreIdentical(){return this.currentHeadSnapshot.trackedElementSignature==this.newHeadSnapshot.trackedElementSignature}async copyNewHeadStylesheetElements(){let e=[];for(let t of this.newHeadStylesheetElements)e.push(Is(t)),document.head.appendChild(t);await Promise.all(e)}copyNewHeadScriptElements(){for(let e of this.newHeadScriptElements)document.head.appendChild(re(e))}removeUnusedDynamicStylesheetElements(){for(let e of this.unusedDynamicStylesheetElements)document.head.removeChild(e)}async mergeProvisionalElements(){let e=[...this.newHeadProvisionalElements];for(let t of this.currentHeadProvisionalElements)if(!this.isCurrentElementInElementList(t,e))document.head.removeChild(t);for(let t of e)document.head.appendChild(t)}isCurrentElementInElementList(e,t){for(let[s,r]of t.entries()){if(e.tagName=="TITLE"){if(r.tagName!="TITLE")continue;if(e.innerHTML==r.innerHTML)return t.splice(s,1),!0}if(r.isEqualNode(e))return t.splice(s,1),!0}return!1}removeCurrentHeadProvisionalElements(){for(let e of this.currentHeadProvisionalElements)document.head.removeChild(e)}copyNewHeadProvisionalElements(){for(let e of this.newHeadProvisionalElements)document.head.appendChild(e)}activateNewBody(){document.adoptNode(this.newElement),this.removeNoscriptElements(),this.activateNewBodyScriptElements()}removeNoscriptElements(){for(let e of this.newElement.querySelectorAll("noscript"))e.remove()}activateNewBodyScriptElements(){for(let e of this.newBodyScriptElements){let t=re(e);e.replaceWith(t)}}async assignNewBody(){await this.renderElement(this.currentElement,this.newElement)}get unusedDynamicStylesheetElements(){return this.oldHeadStylesheetElements.filter((e)=>e.getAttribute("data-turbo-track")==="dynamic")}get oldHeadStylesheetElements(){return this.currentHeadSnapshot.getStylesheetElementsNotInSnapshot(this.newHeadSnapshot)}get newHeadStylesheetElements(){return this.newHeadSnapshot.getStylesheetElementsNotInSnapshot(this.currentHeadSnapshot)}get newHeadScriptElements(){return this.newHeadSnapshot.getScriptElementsNotInSnapshot(this.currentHeadSnapshot)}get currentHeadProvisionalElements(){return this.currentHeadSnapshot.provisionalElements}get newHeadProvisionalElements(){return this.newHeadSnapshot.provisionalElements}get newBodyScriptElements(){return this.newElement.querySelectorAll("script")}}class ze extends ce{static renderElement(e,t){ae(e,t,{callbacks:{beforeNodeMorphed:(s,r)=>{if(qt(s,r)&&!Ht(s))return s.reload(),!1;return!0}}}),R("turbo:morph",{detail:{currentElement:e,newElement:t}})}async preservingPermanentElements(e){return await e()}get renderMethod(){return"morph"}get shouldAutofocus(){return!1}}class Kt extends Ne{constructor(e){super(e,ge)}get snapshots(){return this.entries}}class Xt extends xe{snapshotCache=new Kt(10);lastRenderedLocation=new URL(location.href);forceReloaded=!1;shouldTransitionTo(e){return this.snapshot.prefersViewTransitions&&e.prefersViewTransitions}renderPage(e,t=!1,s=!0,r){let b=new(this.isPageRefresh(r)&&(r?.refresh?.method||this.snapshot.refreshMethod)==="morph"?ze:ce)(this.snapshot,e,t,s);if(!b.shouldRender)this.forceReloaded=!0;else r?.changeHistory();return this.render(b)}renderError(e,t){t?.changeHistory();let s=new Jt(this.snapshot,e,!1);return this.render(s)}clearSnapshotCache(){this.snapshotCache.clear()}async cacheSnapshot(e=this.snapshot){if(e.isCacheable){this.delegate.viewWillCacheSnapshot();let{lastRenderedLocation:t}=this;await ut();let s=e.clone();return this.snapshotCache.put(t,s),s}}getCachedSnapshotForLocation(e){return this.snapshotCache.get(e)}isPageRefresh(e){return!e||this.lastRenderedLocation.pathname===e.location.pathname&&e.action==="replace"}shouldPreserveScrollPosition(e){return this.isPageRefresh(e)&&(e?.refresh?.scroll||this.snapshot.refreshScroll)==="preserve"}get snapshot(){return I.fromElement(this.element)}}class Qt{selector="a[data-turbo-preload]";constructor(e,t){this.delegate=e,this.snapshotCache=t}start(){if(document.readyState==="loading")document.addEventListener("DOMContentLoaded",this.#e);else this.preloadOnLoadLinksForView(document.body)}stop(){document.removeEventListener("DOMContentLoaded",this.#e)}preloadOnLoadLinksForView(e){for(let t of e.querySelectorAll(this.selector))if(this.delegate.shouldPreloadLink(t))this.preloadURL(t)}async preloadURL(e){let t=new URL(e.href);if(this.snapshotCache.has(t))return;await new j(this,P.get,t,new URLSearchParams,e).perform()}prepareRequest(e){e.headers["X-Sec-Purpose"]="prefetch"}async requestSucceededWithResponse(e,t){try{let s=await t.responseHTML,r=I.fromHTMLString(s);this.snapshotCache.put(e.url,r)}catch(s){}}requestStarted(e){}requestErrored(e){}requestFinished(e){}requestPreventedHandlingResponse(e,t){}requestFailedWithResponse(e,t){}#e=()=>{this.preloadOnLoadLinksForView(document.body)}}class Yt{constructor(e){this.session=e}clear(){this.session.clearCache()}resetCacheControl(){this.#e("")}exemptPageFromCache(){this.#e("no-cache")}exemptPageFromPreview(){this.#e("no-preview")}#e(e){Hs("turbo-cache-control",e)}}class Zt{navigator=new Ut(this);history=new Wt(this);view=new Xt(this,document.documentElement);adapter=new Nt(this);pageObserver=new $t(this);cacheObserver=new xt;linkPrefetchObserver=new _t(this,document);linkClickObserver=new We(this,window);formSubmitObserver=new Te(this,document);scrollObserver=new zt(this);streamObserver=new Gt(this);formLinkClickObserver=new _e(this,document.documentElement);frameRedirector=new Vt(this,document.documentElement);streamMessageRenderer=new jt;cache=new Yt(this);enabled=!0;started=!1;#e=150;constructor(e){this.recentRequests=e,this.preloader=new Qt(this,this.view.snapshotCache),this.debouncedRefresh=this.refresh,this.pageRefreshDebouncePeriod=this.pageRefreshDebouncePeriod}start(){if(!this.started)this.pageObserver.start(),this.cacheObserver.start(),this.linkPrefetchObserver.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=!0,this.enabled=!0}disable(){this.enabled=!1}stop(){if(this.started)this.pageObserver.stop(),this.cacheObserver.stop(),this.linkPrefetchObserver.stop(),this.formLinkClickObserver.stop(),this.linkClickObserver.stop(),this.formSubmitObserver.stop(),this.scrollObserver.stop(),this.streamObserver.stop(),this.frameRedirector.stop(),this.history.stop(),this.preloader.stop(),this.started=!1}registerAdapter(e){this.adapter=e}visit(e,t={}){let s=t.frame?document.getElementById(t.frame):null;if(s instanceof k){let r=t.action||z(s);s.delegate.proposeVisitIfNavigatedWithAction(s,r),s.src=e.toString()}else this.navigator.proposeVisit(M(e),t)}refresh(e,t={}){t=typeof t==="string"?{requestId:t}:t;let{method:s,requestId:r,scroll:i}=t,l=r&&this.recentRequests.has(r),b=e===document.baseURI;if(!l&&!this.navigator.currentVisit&&b)this.visit(e,{action:"replace",shouldCacheSnapshot:!1,refresh:{method:s,scroll:i}})}connectStreamSource(e){this.streamObserver.connectStreamSource(e)}disconnectStreamSource(e){this.streamObserver.disconnectStreamSource(e)}renderStreamMessage(e){this.streamMessageRenderer.render(G.wrap(e))}clearCache(){this.view.clearSnapshotCache()}setProgressBarDelay(e){console.warn("Please replace `session.setProgressBarDelay(delay)` with `session.progressBarDelay = delay`. The function is deprecated and will be removed in a future version of Turbo.`"),this.progressBarDelay=e}set progressBarDelay(e){C.drive.progressBarDelay=e}get progressBarDelay(){return C.drive.progressBarDelay}set drive(e){C.drive.enabled=e}get drive(){return C.drive.enabled}set formMode(e){C.forms.mode=e}get formMode(){return C.forms.mode}get location(){return this.history.location}get restorationIdentifier(){return this.history.restorationIdentifier}get pageRefreshDebouncePeriod(){return this.#e}set pageRefreshDebouncePeriod(e){this.refresh=Bs(this.debouncedRefresh.bind(this),e),this.#e=e}shouldPreloadLink(e){let t=e.hasAttribute("data-turbo-method"),s=e.hasAttribute("data-turbo-stream"),r=e.getAttribute("data-turbo-frame"),i=r=="_top"?null:document.getElementById(r)||Q(e,"turbo-frame:not([disabled])");if(t||s||i instanceof k)return!1;else{let l=new URL(e.href);return this.elementIsNavigatable(e)&&N(l,this.snapshot.rootLocation)}}historyPoppedToLocationWithRestorationIdentifierAndDirection(e,t,s){if(this.enabled)this.navigator.startVisit(e,t,{action:"restore",historyChanged:!0,direction:s});else this.adapter.pageInvalidated({reason:"turbo_disabled"})}historyPoppedWithEmptyState(e){this.history.replace(e),this.view.lastRenderedLocation=e,this.view.cacheSnapshot()}scrollPositionChanged(e){this.history.updateRestorationData({scrollPosition:e})}willSubmitFormLinkToLocation(e,t){return this.elementIsNavigatable(e)&&N(t,this.snapshot.rootLocation)}submittedFormLinkToLocation(){}canPrefetchRequestToLocation(e,t){return this.elementIsNavigatable(e)&&N(t,this.snapshot.rootLocation)&&this.navigator.linkPrefetchingIsEnabledForLocation(t)}willFollowLinkToLocation(e,t,s){return this.elementIsNavigatable(e)&&N(t,this.snapshot.rootLocation)&&this.applicationAllowsFollowingLinkToLocation(e,t,s)}followedLinkToLocation(e,t){let s=this.getActionForLink(e),r=e.hasAttribute("data-turbo-stream");this.visit(t.href,{action:s,acceptsStreamResponse:r})}allowsVisitingLocationWithAction(e,t){return this.applicationAllowsVisitingLocation(e)}visitProposedToLocation(e,t){ct(e),this.adapter.visitProposedToLocation(e,t)}visitStarted(e){if(!e.acceptsStreamResponse)ve(document.documentElement),this.view.markVisitDirection(e.direction);ct(e.location),this.notifyApplicationAfterVisitingLocation(e.location,e.action)}visitCompleted(e){this.view.unmarkVisitDirection(),Se(document.documentElement),this.notifyApplicationAfterPageLoad(e.getTimingMetrics())}willSubmitForm(e,t){let s=De(e,t);return this.submissionIsNavigatable(e,t)&&N(M(s),this.snapshot.rootLocation)}formSubmitted(e,t){this.navigator.submitForm(e,t)}pageBecameInteractive(){this.view.lastRenderedLocation=this.location,this.notifyApplicationAfterPageLoad()}pageLoaded(){this.history.assumeControlOfScrollRestoration()}pageWillUnload(){this.history.relinquishControlOfScrollRestoration()}receivedMessageFromStream(e){this.renderStreamMessage(e)}viewWillCacheSnapshot(){this.notifyApplicationBeforeCachingSnapshot()}allowsImmediateRender({element:e},t){let s=this.notifyApplicationBeforeRender(e,t),{defaultPrevented:r,detail:{render:i}}=s;if(this.view.renderer&&i)this.view.renderer.renderElement=i;return!r}viewRenderedSnapshot(e,t,s){this.view.lastRenderedLocation=this.history.location,this.notifyApplicationAfterRender(s)}preloadOnLoadLinksForView(e){this.preloader.preloadOnLoadLinksForView(e)}viewInvalidated(e){this.adapter.pageInvalidated(e)}frameLoaded(e){this.notifyApplicationAfterFrameLoad(e)}frameRendered(e,t){this.notifyApplicationAfterFrameRender(e,t)}applicationAllowsFollowingLinkToLocation(e,t,s){return!this.notifyApplicationAfterClickingLinkToLocation(e,t,s).defaultPrevented}applicationAllowsVisitingLocation(e){return!this.notifyApplicationBeforeVisitingLocation(e).defaultPrevented}notifyApplicationAfterClickingLinkToLocation(e,t,s){return R("turbo:click",{target:e,detail:{url:t.href,originalEvent:s},cancelable:!0})}notifyApplicationBeforeVisitingLocation(e){return R("turbo:before-visit",{detail:{url:e.href},cancelable:!0})}notifyApplicationAfterVisitingLocation(e,t){return R("turbo:visit",{detail:{url:e.href,action:t}})}notifyApplicationBeforeCachingSnapshot(){return R("turbo:before-cache")}notifyApplicationBeforeRender(e,t){return R("turbo:before-render",{detail:{newBody:e,...t},cancelable:!0})}notifyApplicationAfterRender(e){return R("turbo:render",{detail:{renderMethod:e}})}notifyApplicationAfterPageLoad(e={}){return R("turbo:load",{detail:{url:this.location.href,timing:e}})}notifyApplicationAfterFrameLoad(e){return R("turbo:frame-load",{target:e})}notifyApplicationAfterFrameRender(e,t){return R("turbo:frame-render",{detail:{fetchResponse:e},target:t,cancelable:!0})}submissionIsNavigatable(e,t){if(C.forms.mode=="off")return!1;else{let s=t?this.elementIsNavigatable(t):!0;if(C.forms.mode=="optin")return s&&e.closest('[data-turbo="true"]')!=null;else return s&&this.elementIsNavigatable(e)}}elementIsNavigatable(e){let t=Q(e,"[data-turbo]"),s=Q(e,"turbo-frame");if(C.drive.enabled||s)if(t)return t.getAttribute("data-turbo")!="false";else return!0;else if(t)return t.getAttribute("data-turbo")=="true";else return!1}getActionForLink(e){return z(e)||"advance"}get snapshot(){return this.view.snapshot}}function ct(e){Object.defineProperties(e,Mr)}var Mr={absoluteURL:{get(){return this.toString()}}},L=new Zt(At),{cache:es,navigator:ts}=L;function je(){L.start()}function ss(e){L.registerAdapter(e)}function rs(e,t){L.visit(e,t)}function le(e){L.connectStreamSource(e)}function he(e){L.disconnectStreamSource(e)}function is(e){L.renderStreamMessage(e)}function ns(e){console.warn("Please replace `Turbo.setProgressBarDelay(delay)` with `Turbo.config.drive.progressBarDelay = delay`. The top-level function is deprecated and will be removed in a future version of Turbo.`"),C.drive.progressBarDelay=e}function os(e){console.warn("Please replace `Turbo.setConfirmMethod(confirmMethod)` with `Turbo.config.forms.confirm = confirmMethod`. The top-level function is deprecated and will be removed in a future version of Turbo.`"),C.forms.confirm=e}function as(e){console.warn("Please replace `Turbo.setFormMode(mode)` with `Turbo.config.forms.mode = mode`. The top-level function is deprecated and will be removed in a future version of Turbo.`"),C.forms.mode=e}function cs(e,t){ze.renderElement(e,t)}function ls(e,t){$e.renderElement(e,t)}var Pr=Object.freeze({__proto__:null,PageRenderer:ce,PageSnapshot:I,FrameRenderer:oe,fetch:Oe,config:C,session:L,cache:es,navigator:ts,start:je,registerAdapter:ss,visit:rs,connectStreamSource:le,disconnectStreamSource:he,renderStreamMessage:is,setProgressBarDelay:ns,setConfirmMethod:os,setFormMode:as,morphBodyElements:cs,morphTurboFrameElements:ls,morphChildren:Le,morphElements:ae});class hs extends Error{}class us{fetchResponseLoaded=(e)=>Promise.resolve();#e=null;#t=()=>{};#s=!1;#o=!1;#a=new Set;#i=!1;action=null;constructor(e){this.element=e,this.view=new It(this,this.element),this.appearanceObserver=new Lt(this,this.element),this.formLinkClickObserver=new _e(this,this.element),this.linkInterceptor=new Ve(this,this.element),this.restorationIdentifier=V(),this.formSubmitObserver=new Te(this,this.element)}connect(){if(!this.#s){if(this.#s=!0,this.loadingStyle==U.lazy)this.appearanceObserver.start();else this.#r();this.formLinkClickObserver.start(),this.linkInterceptor.start(),this.formSubmitObserver.start()}}disconnect(){if(this.#s){if(this.#s=!1,this.appearanceObserver.stop(),this.formLinkClickObserver.stop(),this.linkInterceptor.stop(),this.formSubmitObserver.stop(),!this.element.hasAttribute("recurse"))this.#e?.cancel()}}disabledChanged(){if(this.disabled)this.#e?.cancel();else if(this.loadingStyle==U.eager)this.#r()}sourceURLChanged(){if(this.#S("src"))return;if(!this.sourceURL)this.#e?.cancel();if(this.element.isConnected)this.complete=!1;if(this.loadingStyle==U.eager||this.#o)this.#r()}sourceURLReloaded(){let{refresh:e,src:t}=this.element;return this.#i=t&&e==="morph",this.element.removeAttribute("complete"),this.element.src=null,this.element.src=t,this.element.loaded}loadingStyleChanged(){if(this.loadingStyle==U.lazy)this.appearanceObserver.start();else this.appearanceObserver.stop(),this.#r()}async#r(){if(this.enabled&&this.isActive&&!this.complete&&this.sourceURL)this.element.loaded=this.#d(M(this.sourceURL)),this.appearanceObserver.stop(),await this.element.loaded,this.#o=!0}async loadResponse(e){if(e.redirected||e.succeeded&&e.isHTML)this.sourceURL=e.response.url;try{let t=await e.responseHTML;if(t){let s=dt(t);if(I.fromDocument(s).isVisitable)await this.#c(e,s);else await this.#f(e)}}finally{this.#i=!1,this.fetchResponseLoaded=()=>Promise.resolve()}}elementAppearedInViewport(e){this.proposeVisitIfNavigatedWithAction(e,z(e)),this.#r()}willSubmitFormLinkToLocation(e){return this.#l(e)}submittedFormLinkToLocation(e,t,s){let r=this.#n(e);if(r)s.setAttribute("data-turbo-frame",r.id)}shouldInterceptLinkClick(e,t,s){return this.#l(e)}linkClickIntercepted(e,t){this.#m(e,t)}willSubmitForm(e,t){return e.closest("turbo-frame")==this.element&&this.#l(e,t)}formSubmitted(e,t){if(this.formSubmission)this.formSubmission.stop();this.formSubmission=new Ae(this,e,t);let{fetchRequest:s}=this.formSubmission,r=this.#n(e,t);this.prepareRequest(s,r),this.formSubmission.start()}prepareRequest(e,t=this){if(e.headers["Turbo-Frame"]=t.id,this.currentNavigationElement?.hasAttribute("data-turbo-stream"))e.acceptResponseType(G.contentType)}requestStarted(e){ve(this.element)}requestPreventedHandlingResponse(e,t){this.#t()}async requestSucceededWithResponse(e,t){await this.loadResponse(t),this.#t()}async requestFailedWithResponse(e,t){await this.loadResponse(t),this.#t()}requestErrored(e,t){console.error(t),this.#t()}requestFinished(e){Se(this.element)}formSubmissionStarted({formElement:e}){ve(e,this.#n(e))}formSubmissionSucceededWithResponse(e,t){let s=this.#n(e.formElement,e.submitter);if(s.delegate.proposeVisitIfNavigatedWithAction(s,z(e.submitter,e.formElement,s)),s.delegate.loadResponse(t),!e.isSafe)L.clearCache()}formSubmissionFailedWithResponse(e,t){this.element.delegate.loadResponse(t),L.clearCache()}formSubmissionErrored(e,t){console.error(t)}formSubmissionFinished({formElement:e}){Se(e,this.#n(e))}allowsImmediateRender({element:e},t){let s=R("turbo:before-frame-render",{target:this.element,detail:{newFrame:e,...t},cancelable:!0}),{defaultPrevented:r,detail:{render:i}}=s;if(this.view.renderer&&i)this.view.renderer.renderElement=i;return!r}viewRenderedSnapshot(e,t,s){}preloadOnLoadLinksForView(e){L.preloadOnLoadLinksForView(e)}viewInvalidated(){}willRenderFrame(e,t){this.previousFrameElement=e.cloneNode(!0)}visitCachedSnapshot=({element:e})=>{let t=e.querySelector("#"+this.element.id);if(t&&this.previousFrameElement)t.replaceChildren(...this.previousFrameElement.children);delete this.previousFrameElement};async#c(e,t){let s=await this.extractForeignFrameElement(t.body),r=this.#i?$e:oe;if(s){let i=new ne(s),l=new r(this,this.view.snapshot,i,!1,!1);if(this.view.renderPromise)await this.view.renderPromise;this.changeHistory(),await this.view.render(l),this.complete=!0,L.frameRendered(e,this.element),L.frameLoaded(this.element),await this.fetchResponseLoaded(e)}else if(this.#p(e))this.#g(e)}async#d(e){let t=new j(this,P.get,e,new URLSearchParams,this.element);return this.#e?.cancel(),this.#e=t,new Promise((s)=>{this.#t=()=>{this.#t=()=>{},this.#e=null,s()},t.perform()})}#m(e,t,s){let r=this.#n(e,s);r.delegate.proposeVisitIfNavigatedWithAction(r,z(s,e,r)),this.#y(e,()=>{r.src=t})}proposeVisitIfNavigatedWithAction(e,t=null){if(this.action=t,this.action){let s=I.fromElement(e).clone(),{visitCachedSnapshot:r}=e.delegate;e.delegate.fetchResponseLoaded=async(i)=>{if(e.src){let{statusCode:l,redirected:b}=i,E=await i.responseHTML,H={response:{statusCode:l,redirected:b,responseHTML:E},visitCachedSnapshot:r,willRender:!1,updateHistory:!1,restorationIdentifier:this.restorationIdentifier,snapshot:s};if(this.action)H.action=this.action;L.visit(e.src,H)}}}}changeHistory(){if(this.action){let e=ft(this.action);L.history.update(e,M(this.element.src||""),this.restorationIdentifier)}}async#f(e){console.warn(`The response (${e.statusCode}) from <turbo-frame id="${this.element.id}"> is performing a full page visit due to turbo-visit-control.`),await this.#h(e.response)}#p(e){this.element.setAttribute("complete","");let t=e.response,s=async(i,l)=>{if(i instanceof Response)this.#h(i);else L.visit(i,l)};return!R("turbo:frame-missing",{target:this.element,detail:{response:t,visit:s},cancelable:!0}).defaultPrevented}#g(e){this.view.missing(),this.#b(e)}#b(e){let t=`The response (${e.statusCode}) did not contain the expected <turbo-frame id="${this.element.id}"> and will be ignored. To perform a full page visit instead, set turbo-visit-control to reload.`;throw new hs(t)}async#h(e){let t=new ie(e),s=await t.responseHTML,{location:r,redirected:i,statusCode:l}=t;return L.visit(r,{response:{redirected:i,statusCode:l,responseHTML:s}})}#n(e,t){let s=be("data-turbo-frame",t,e)||this.element.getAttribute("target"),r=this.#u(s);return r instanceof k?r:this.element}async extractForeignFrameElement(e){let t,s=CSS.escape(this.id);try{if(t=lt(e.querySelector(`turbo-frame#${s}`),this.sourceURL),t)return t;if(t=lt(e.querySelector(`turbo-frame[src][recurse~=${s}]`),this.sourceURL),t)return await t.loaded,await this.extractForeignFrameElement(t)}catch(r){return console.error(r),new k}return null}#v(e,t){let s=De(e,t);return N(M(s),this.rootLocation)}#l(e,t){let s=be("data-turbo-frame",t,e)||this.element.getAttribute("target");if(e instanceof HTMLFormElement&&!this.#v(e,t))return!1;if(!this.enabled||s=="_top")return!1;if(s){let r=this.#u(s);if(r)return!r.disabled;else if(s=="_parent")return!1}if(!L.elementIsNavigatable(e))return!1;if(t&&!L.elementIsNavigatable(t))return!1;return!0}get id(){return this.element.id}get disabled(){return this.element.disabled}get enabled(){return!this.disabled}get sourceURL(){if(this.element.src)return this.element.src}set sourceURL(e){this.#w("src",()=>{this.element.src=e??null})}get loadingStyle(){return this.element.loading}get isLoading(){return this.formSubmission!==void 0||this.#t()!==void 0}get complete(){return this.element.hasAttribute("complete")}set complete(e){if(e)this.element.setAttribute("complete","");else this.element.removeAttribute("complete")}get isActive(){return this.element.isActive&&this.#s}get rootLocation(){let t=this.element.ownerDocument.querySelector('meta[name="turbo-root"]')?.content??"/";return M(t)}#S(e){return this.#a.has(e)}#w(e,t){this.#a.add(e),t(),this.#a.delete(e)}#y(e,t){this.currentNavigationElement=e,t(),delete this.currentNavigationElement}#u(e){if(e!=null){let t=e==="_parent"?this.element.parentElement.closest("turbo-frame"):document.getElementById(e);if(t instanceof k)return t}}}function lt(e,t){if(e){let s=e.getAttribute("src");if(s!=null&&t!=null&&yt(s,t))throw Error(`Matching <turbo-frame id="${e.id}"> element has a source URL which references itself`);if(e.ownerDocument!==document)e=document.importNode(e,!0);if(e instanceof k)return e.connectedCallback(),e.disconnectedCallback(),e}}var Ge={after(){this.removeDuplicateTargetSiblings(),this.targetElements.forEach((e)=>e.parentElement?.insertBefore(this.templateContent,e.nextSibling))},append(){this.removeDuplicateTargetChildren(),this.targetElements.forEach((e)=>e.append(this.templateContent))},before(){this.removeDuplicateTargetSiblings(),this.targetElements.forEach((e)=>e.parentElement?.insertBefore(this.templateContent,e))},prepend(){this.removeDuplicateTargetChildren(),this.targetElements.forEach((e)=>e.prepend(this.templateContent))},remove(){this.targetElements.forEach((e)=>e.remove())},replace(){let e=this.getAttribute("method");this.targetElements.forEach((t)=>{if(e==="morph")ae(t,this.templateContent);else t.replaceWith(this.templateContent)})},update(){let e=this.getAttribute("method");this.targetElements.forEach((t)=>{if(e==="morph")Le(t,this.templateContent);else t.innerHTML="",t.append(this.templateContent)})},refresh(){let e=this.getAttribute("method"),t=this.requestId,s=this.getAttribute("scroll");L.refresh(this.baseURI,{method:e,requestId:t,scroll:s})}};class Ce extends HTMLElement{static async renderElement(e){await e.performAction()}async connectedCallback(){try{await this.render()}catch(e){console.error(e)}finally{this.disconnect()}}async render(){return this.renderPromise??=(async()=>{let e=this.beforeRenderEvent;if(this.dispatchEvent(e))await te(),await e.detail.render(this)})()}disconnect(){try{this.remove()}catch{}}removeDuplicateTargetChildren(){this.duplicateChildren.forEach((e)=>e.remove())}get duplicateChildren(){let e=this.targetElements.flatMap((s)=>[...s.children]).filter((s)=>!!s.getAttribute("id")),t=[...this.templateContent?.children||[]].filter((s)=>!!s.getAttribute("id")).map((s)=>s.getAttribute("id"));return e.filter((s)=>t.includes(s.getAttribute("id")))}removeDuplicateTargetSiblings(){this.duplicateSiblings.forEach((e)=>e.remove())}get duplicateSiblings(){let e=this.targetElements.flatMap((s)=>[...s.parentElement.children]).filter((s)=>!!s.id),t=[...this.templateContent?.children||[]].filter((s)=>!!s.id).map((s)=>s.id);return e.filter((s)=>t.includes(s.id))}get performAction(){if(this.action){let e=Ge[this.action];if(e)return e;this.#e("unknown action")}this.#e("action attribute is missing")}get targetElements(){if(this.target)return this.targetElementsById;else if(this.targets)return this.targetElementsByQuery;else this.#e("target or targets attribute is missing")}get templateContent(){return this.templateElement.content.cloneNode(!0)}get templateElement(){if(this.firstElementChild===null){let e=this.ownerDocument.createElement("template");return this.appendChild(e),e}else if(this.firstElementChild instanceof HTMLTemplateElement)return this.firstElementChild;this.#e("first child element must be a <template> element")}get action(){return this.getAttribute("action")}get target(){return this.getAttribute("target")}get targets(){return this.getAttribute("targets")}get requestId(){return this.getAttribute("request-id")}#e(e){throw Error(`${this.description}: ${e}`)}get description(){return(this.outerHTML.match(/<[^>]+>/)??[])[0]??"<turbo-stream>"}get beforeRenderEvent(){return new CustomEvent("turbo:before-stream-render",{bubbles:!0,cancelable:!0,detail:{newStream:this,render:Ce.renderElement}})}get targetElementsById(){let e=this.ownerDocument?.getElementById(this.target);if(e!==null)return[e];else return[]}get targetElementsByQuery(){let e=this.ownerDocument?.querySelectorAll(this.targets);if(e.length!==0)return Array.prototype.slice.call(e);else return[]}}class Je extends HTMLElement{streamSource=null;connectedCallback(){this.streamSource=this.src.match(/^ws{1,2}:/)?new WebSocket(this.src):new EventSource(this.src),le(this.streamSource)}disconnectedCallback(){if(this.streamSource)this.streamSource.close(),he(this.streamSource)}get src(){return this.getAttribute("src")||""}}k.delegateConstructor=us;if(customElements.get("turbo-frame")===void 0)customElements.define("turbo-frame",k);if(customElements.get("turbo-stream")===void 0)customElements.define("turbo-stream",Ce);if(customElements.get("turbo-stream-source")===void 0)customElements.define("turbo-stream-source",Je);(()=>{let e=document.currentScript;if(!e)return;if(e.hasAttribute("data-turbo-suppress-warning"))return;let t=e.parentElement;while(t){if(t==document.body)return console.warn(mt`
|
|
21
|
+
You are loading Turbo from a <script> element inside the <body> element. This is probably not what you meant to do!
|
|
22
|
+
|
|
23
|
+
Load your application’s JavaScript bundle inside the <head> element instead. <script> elements in <body> are evaluated with each page change.
|
|
24
|
+
|
|
25
|
+
For more information, see: https://turbo.hotwired.dev/handbook/building#working-with-script-elements
|
|
26
|
+
|
|
27
|
+
——
|
|
28
|
+
Suppress this warning by adding a "data-turbo-suppress-warning" attribute to: %s
|
|
29
|
+
`,e.outerHTML);t=t.parentElement}})();window.Turbo={...Pr,StreamActions:Ge};je();var Ss={};rt(Ss,{createConsumer:()=>vs,getConsumer:()=>bs,setConsumer:()=>et,subscribeTo:()=>tt});var J={logger:typeof console<"u"?console:void 0,WebSocket:typeof WebSocket<"u"?WebSocket:void 0};var y={log(...e){if(this.enabled)e.push(Date.now()),J.logger.log("[ActionCable]",...e)}};var ue=()=>new Date().getTime(),Me=(e)=>(ue()-e)/1000;class Pe{constructor(e){this.visibilityDidChange=this.visibilityDidChange.bind(this),this.connection=e,this.reconnectAttempts=0}start(){if(!this.isRunning())this.startedAt=ue(),delete this.stoppedAt,this.startPolling(),addEventListener("visibilitychange",this.visibilityDidChange),y.log(`ConnectionMonitor started. stale threshold = ${this.constructor.staleThreshold} s`)}stop(){if(this.isRunning())this.stoppedAt=ue(),this.stopPolling(),removeEventListener("visibilitychange",this.visibilityDidChange),y.log("ConnectionMonitor stopped")}isRunning(){return this.startedAt&&!this.stoppedAt}recordMessage(){this.pingedAt=ue()}recordConnect(){this.reconnectAttempts=0,delete this.disconnectedAt,y.log("ConnectionMonitor recorded connect")}recordDisconnect(){this.disconnectedAt=ue(),y.log("ConnectionMonitor recorded disconnect")}startPolling(){this.stopPolling(),this.poll()}stopPolling(){clearTimeout(this.pollTimeout)}poll(){this.pollTimeout=setTimeout(()=>{this.reconnectIfStale(),this.poll()},this.getPollInterval())}getPollInterval(){let{staleThreshold:e,reconnectionBackoffRate:t}=this.constructor,s=Math.pow(1+t,Math.min(this.reconnectAttempts,10)),i=(this.reconnectAttempts===0?1:t)*Math.random();return e*1000*s*(1+i)}reconnectIfStale(){if(this.connectionIsStale())if(y.log(`ConnectionMonitor detected stale connection. reconnectAttempts = ${this.reconnectAttempts}, time stale = ${Me(this.refreshedAt)} s, stale threshold = ${this.constructor.staleThreshold} s`),this.reconnectAttempts++,this.disconnectedRecently())y.log(`ConnectionMonitor skipping reopening recent disconnect. time disconnected = ${Me(this.disconnectedAt)} s`);else y.log("ConnectionMonitor reopening"),this.connection.reopen()}get refreshedAt(){return this.pingedAt?this.pingedAt:this.startedAt}connectionIsStale(){return Me(this.refreshedAt)>this.constructor.staleThreshold}disconnectedRecently(){return this.disconnectedAt&&Me(this.disconnectedAt)<this.constructor.staleThreshold}visibilityDidChange(){if(document.visibilityState==="visible")setTimeout(()=>{if(this.connectionIsStale()||!this.connection.isOpen())y.log(`ConnectionMonitor reopening stale connection on visibilitychange. visibilityState = ${document.visibilityState}`),this.connection.reopen()},200)}}Pe.staleThreshold=6;Pe.reconnectionBackoffRate=0.15;var Xe=Pe;var ke={message_types:{welcome:"welcome",disconnect:"disconnect",ping:"ping",history:"history",confirmation:"confirm_subscription",rejection:"reject_subscription"},disconnect_reasons:{unauthorized:"unauthorized",invalid_request:"invalid_request",server_restart:"server_restart",remote:"remote"},default_mount_path:"/cable",protocols:["actioncable-v1-json","actioncable-unsupported"]};var{message_types:Z,protocols:Qe}=ke,kr=Qe.slice(0,Qe.length-1),ds=[].indexOf;class Ie{constructor(e){this.open=this.open.bind(this),this.consumer=e,this.subscriptions=this.consumer.subscriptions,this.monitor=new Xe(this),this.disconnected=!0}send(e){if(this.isOpen())return this.webSocket.send(JSON.stringify(e)),!0;else return!1}open(){if(this.isActive())return y.log(`Attempted to open WebSocket, but existing socket is ${this.getState()}`),!1;else{let e=[...Qe,...this.consumer.subprotocols||[]];if(y.log(`Opening WebSocket, current state is ${this.getState()}, subprotocols: ${e}`),this.webSocket)this.uninstallEventHandlers();return this.webSocket=new J.WebSocket(this.consumer.url,e),this.installEventHandlers(),this.monitor.start(),!0}}close({allowReconnect:e}={allowReconnect:!0}){if(!e)this.monitor.stop();if(this.isOpen())return this.webSocket.close()}reopen(){if(y.log(`Reopening WebSocket, current state is ${this.getState()}`),this.isActive())try{return this.close()}catch(e){y.log("Failed to reopen WebSocket",e)}finally{y.log(`Reopening WebSocket in ${this.constructor.reopenDelay}ms`),setTimeout(this.open,this.constructor.reopenDelay)}else return this.open()}getProtocol(){if(this.webSocket)return this.webSocket.protocol}isOpen(){return this.isState("open")}isActive(){return this.isState("open","connecting")}triedToReconnect(){return this.monitor.reconnectAttempts>0}isProtocolSupported(){return ds.call(kr,this.getProtocol())>=0}isState(...e){return ds.call(e,this.getState())>=0}getState(){if(this.webSocket){for(let e in J.WebSocket)if(J.WebSocket[e]===this.webSocket.readyState)return e.toLowerCase()}return null}installEventHandlers(){for(let e in this.events){let t=this.events[e].bind(this);this.webSocket[`on${e}`]=t}}uninstallEventHandlers(){for(let e in this.events)this.webSocket[`on${e}`]=function(){}}}Ie.reopenDelay=500;Ie.prototype.events={message(e){if(!this.isProtocolSupported())return;let{identifier:t,ids:s,message:r,reason:i,reconnect:l,type:b,broadcasting:E,id:q}=JSON.parse(e.data);switch(this.monitor.recordMessage(),b){case Z.welcome:if(this.triedToReconnect())this.reconnectAttempted=!0;return this.monitor.recordConnect(),this.subscriptions.reload();case Z.disconnect:return y.log(`Disconnecting. Reason: ${i}`),this.close({allowReconnect:l});case Z.history:return this.subscriptions.ingestHistory(t,E,r);case Z.ping:return null;case Z.confirmation:if(this.subscriptions.confirmSubscription(t,s),this.reconnectAttempted)return this.reconnectAttempted=!1,this.subscriptions.notify(t,"connected",{reconnected:!0});else return this.subscriptions.notify(t,"connected",{reconnected:!1});case Z.rejection:return this.subscriptions.reject(t);default:return this.subscriptions.receive(t,r,q,E)}},open(){if(y.log(`WebSocket onopen event, using '${this.getProtocol()}' subprotocol`),this.disconnected=!1,!this.isProtocolSupported())return y.log("Protocol is unsupported. Stopping monitor and disconnecting."),this.close({allowReconnect:!1})},close(e){if(y.log("WebSocket onclose event"),this.disconnected)return;return this.disconnected=!0,this.monitor.recordDisconnect(),this.subscriptions.notifyAll("disconnected",{willAttemptReconnect:this.monitor.isRunning()})},error(){y.log("WebSocket onerror event")}};var Ye=Ie;class qe{constructor(e,t,s){this.subscription=e,this.broadcasting=t,this.id=s,this.recovering=!1,this.queue=[]}isBehind(e){return this.id!=null&&this.id<e}recover(e,t,s){this.queue.push({id:t,message:s}),this.requestHistory(e)}requestHistory(e){if(!this.recovering)this.recovering=!0,e.sendCommand(this.subscription,"history",{broadcasting:this.broadcasting,id:this.id})}restartRecovery(e){this.recovering=!1,this.requestHistory(e)}processMessage(e,t,s){if(this.id!=null&&e<=this.id)return!0;if(this.id==null||e===this.id+1)return this.id=e,s(t),!0;return!1}processMessages(e,t){let s=e.map(({id:r,payload:i})=>({id:r,message:JSON.parse(i)}));return this.queue=s.concat(this.queue),this.queue.sort((r,i)=>r.id-i.id).forEach(({id:r,message:i})=>{if(this.id==null||r>this.id)this.id=r,t(i)}),this.queue=[],this.recovering=!1,this.subscription}processQueue(e){let t=[];this.queue.sort((s,r)=>s.id-r.id).filter(({id:s})=>s>this.id).forEach(({id:s,message:r})=>{if(!this.processMessage(s,r,e))t.push({id:s,message:r})}),this.queue=t}}var Ir=function(e,t){if(t!=null)for(let s in t){let r=t[s];e[s]=r}return e};class de{constructor(e,t={},s){this.consumer=e,this.identifier=JSON.stringify(t),this.streams={},Ir(this,s)}perform(e,t={}){return t.action=e,this.send(t)}send(e){return this.consumer.send({command:"message",identifier:this.identifier,data:JSON.stringify(e)})}unsubscribe(){return this.consumer.subscriptions.remove(this)}reset(){this.streams={}}findOrCreateStream(e,t=null){if(this.streams[e]==null)this.streams[e]=new qe(this,e,t);return this.streams[e]}}class ms{constructor(e){this.subscriptions=e,this.pendingSubscriptions=[]}guarantee(e){if(this.pendingSubscriptions.indexOf(e)==-1)y.log(`SubscriptionGuarantor guaranteeing ${e.identifier}`),this.pendingSubscriptions.push(e);else y.log(`SubscriptionGuarantor already guaranteeing ${e.identifier}`);this.startGuaranteeing()}forget(e){y.log(`SubscriptionGuarantor forgetting ${e.identifier}`),this.pendingSubscriptions=this.pendingSubscriptions.filter((t)=>t!==e)}startGuaranteeing(){this.stopGuaranteeing(),this.retrySubscribing()}stopGuaranteeing(){clearTimeout(this.retryTimeout)}retrySubscribing(){this.retryTimeout=setTimeout(()=>{if(this.subscriptions&&typeof this.subscriptions.subscribe==="function")this.pendingSubscriptions.map((e)=>{y.log(`SubscriptionGuarantor resubscribing ${e.identifier}`),this.subscriptions.subscribe(e)})},500)}}var Ze=ms;class me{constructor(e){this.consumer=e,this.guarantor=new Ze(this),this.subscriptions=[]}create(e,t){let s=e,r=typeof s==="object"?s:{channel:s},i=new de(this.consumer,r,t);return this.add(i)}add(e){return this.subscriptions.push(e),this.consumer.ensureActiveConnection(),this.notify(e,"initialized"),this.subscribe(e),e}remove(e){if(this.forget(e),!this.findAll(e.identifier).length)this.sendCommand(e,"unsubscribe");return e}reject(e){return this.findAll(e).map((t)=>(this.forget(t),this.notify(t,"rejected"),t))}forget(e){return this.guarantor.forget(e),e.reset(),this.subscriptions=this.subscriptions.filter((t)=>t!==e),e}findAll(e){return this.subscriptions.filter((t)=>t.identifier===e)}reload(){return this.subscriptions.map((e)=>this.subscribe(e))}notifyAll(e,...t){return this.subscriptions.map((s)=>this.notify(s,e,...t))}notify(e,t,...s){let r;if(typeof e==="string")r=this.findAll(e);else r=[e];return r.map((i)=>typeof i[t]==="function"?i[t](...s):void 0)}subscribe(e){if(this.sendCommand(e,"subscribe"))this.guarantor.guarantee(e)}confirmSubscription(e,t){y.log(`Subscription confirmed ${e}`),this.findAll(e).forEach((s)=>{if(t!=null)Object.entries(t).forEach(([r,i])=>{let l=s.findOrCreateStream(r,i);if(l.isBehind(i))l.restartRecovery(this)});this.guarantor.forget(s)})}sendCommand(e,t,s={}){let{identifier:r}=e;return this.consumer.send({command:t,identifier:r,...s})}receive(e,t,s,r){if(s==null||r==null)return this.notify(e,"received",t);return this.findAll(e).map((i)=>{let l=i.findOrCreateStream(r),b=(E)=>this.notify(i,"received",E);if(l.processMessage(s,t,b))l.processQueue(b);else l.recover(this,s,t);return i})}ingestHistory(e,t,{messages:s=[],id:r}){return this.findAll(e).map((i)=>(i.findOrCreateStream(t,r).processMessages(s,(b)=>this.notify(i,"received",b)),i))}}class He{constructor(e){this._url=e,this.subscriptions=new me(this),this.connection=new Ye(this),this.subprotocols=[]}get url(){return fs(this._url)}send(e){return this.connection.send(e)}connect(){return this.connection.open()}disconnect(){return this.connection.close({allowReconnect:!1})}ensureActiveConnection(){if(!this.connection.isActive())return this.connection.open()}addSubProtocol(e){this.subprotocols=[...this.subprotocols,e]}}function fs(e){if(typeof e==="function")e=e();if(e&&!/^wss?:/i.test(e)){let t=document.createElement("a");return t.href=e,t.href=t.href,t.protocol=t.protocol.replace("http","ws"),t.href}else return e}function ps(e=qr("url")||ke.default_mount_path){return new He(e)}function qr(e){let t=document.head.querySelector(`meta[name='action-cable-${e}']`);if(t)return t.getAttribute("content")}var gs;async function bs(){return gs||et(vs().then(et))}function et(e){return gs=e}async function vs(...e){return ps(...e)}async function tt(e,t){let{subscriptions:s}=await bs();return s.create(e,t)}function fe(e){if(!e||typeof e!=="object")return e;if(e instanceof Date||e instanceof RegExp)return e;if(Array.isArray(e))return e.map(fe);return Object.keys(e).reduce(function(t,s){var r=s[0].toLowerCase()+s.slice(1).replace(/([A-Z]+)/g,function(i,l){return"_"+l.toLowerCase()});return t[r]=fe(e[s]),t},{})}class ws extends HTMLElement{static observedAttributes=["channel","signed-stream-name"];async connectedCallback(){le(this),this.subscription=await tt(this.channel,{received:this.dispatchMessageEvent.bind(this),connected:this.subscriptionConnected.bind(this),disconnected:this.subscriptionDisconnected.bind(this)})}disconnectedCallback(){if(he(this),this.subscription)this.subscription.unsubscribe();this.subscriptionDisconnected()}attributeChangedCallback(){if(this.subscription)this.disconnectedCallback(),this.connectedCallback()}dispatchMessageEvent(e){let t=new MessageEvent("message",{data:e});return this.dispatchEvent(t)}subscriptionConnected(){this.setAttribute("connected","")}subscriptionDisconnected(){this.removeAttribute("connected")}get channel(){let e=this.getAttribute("channel"),t=this.getAttribute("signed-stream-name");return{channel:e,signed_stream_name:t,...fe({...this.dataset})}}}if(customElements.get("turbo-cable-stream-source")===void 0)customElements.define("turbo-cable-stream-source",ws);function ys(e){if(e.target instanceof HTMLFormElement){let{target:t,detail:{fetchOptions:s}}=e;t.addEventListener("turbo:submit-start",({detail:{formSubmission:{submitter:r}}})=>{let i=Br(s.body)?s.body:new URLSearchParams,l=Hr(r,i,t);if(!/get/i.test(l)){if(/post/i.test(l))i.delete("_method");else i.set("_method",l);s.method="post"}},{once:!0})}}function Hr(e,t,s){let r=Fr(e),i=t.get("_method"),l=s.getAttribute("method")||"get";if(typeof r=="string")return r;else if(typeof i=="string")return i;else return l}function Fr(e){if(e instanceof HTMLButtonElement||e instanceof HTMLInputElement)if(e.name==="_method")return e.value;else if(e.hasAttribute("formmethod"))return e.formMethod;else return null;else return null}function Br(e){return e instanceof FormData||e instanceof URLSearchParams}window.Turbo=Ke;addEventListener("turbo:before-fetch-request",ys);export{Ke as Turbo,Ss as cable};
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
import adapters from "./adapters"
|
|
2
|
+
import ConnectionMonitor from "./connection_monitor"
|
|
3
|
+
import INTERNAL from "./internal"
|
|
4
|
+
import logger from "./logger"
|
|
5
|
+
|
|
6
|
+
// Encapsulate the cable connection held by the consumer. This is an internal class not intended for direct user manipulation.
|
|
7
|
+
|
|
8
|
+
const {message_types, protocols} = INTERNAL
|
|
9
|
+
const supportedProtocols = protocols.slice(0, protocols.length - 1)
|
|
10
|
+
|
|
11
|
+
const indexOf = [].indexOf
|
|
12
|
+
|
|
13
|
+
class Connection {
|
|
14
|
+
constructor(consumer) {
|
|
15
|
+
this.open = this.open.bind(this)
|
|
16
|
+
this.consumer = consumer
|
|
17
|
+
this.subscriptions = this.consumer.subscriptions
|
|
18
|
+
this.monitor = new ConnectionMonitor(this)
|
|
19
|
+
this.disconnected = true
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
send(data) {
|
|
23
|
+
if (this.isOpen()) {
|
|
24
|
+
this.webSocket.send(JSON.stringify(data))
|
|
25
|
+
return true
|
|
26
|
+
} else {
|
|
27
|
+
return false
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
open() {
|
|
32
|
+
if (this.isActive()) {
|
|
33
|
+
logger.log(`Attempted to open WebSocket, but existing socket is ${this.getState()}`)
|
|
34
|
+
return false
|
|
35
|
+
} else {
|
|
36
|
+
const socketProtocols = [...protocols, ...this.consumer.subprotocols || []]
|
|
37
|
+
logger.log(`Opening WebSocket, current state is ${this.getState()}, subprotocols: ${socketProtocols}`)
|
|
38
|
+
if (this.webSocket) { this.uninstallEventHandlers() }
|
|
39
|
+
this.webSocket = new adapters.WebSocket(this.consumer.url, socketProtocols)
|
|
40
|
+
this.installEventHandlers()
|
|
41
|
+
this.monitor.start()
|
|
42
|
+
return true
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
close({allowReconnect} = {allowReconnect: true}) {
|
|
47
|
+
if (!allowReconnect) { this.monitor.stop() }
|
|
48
|
+
// Avoid closing websockets in a "connecting" state due to Safari 15.1+ bug. See: https://github.com/rails/rails/issues/43835#issuecomment-1002288478
|
|
49
|
+
if (this.isOpen()) {
|
|
50
|
+
return this.webSocket.close()
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
reopen() {
|
|
55
|
+
logger.log(`Reopening WebSocket, current state is ${this.getState()}`)
|
|
56
|
+
if (this.isActive()) {
|
|
57
|
+
try {
|
|
58
|
+
return this.close()
|
|
59
|
+
} catch (error) {
|
|
60
|
+
logger.log("Failed to reopen WebSocket", error)
|
|
61
|
+
}
|
|
62
|
+
finally {
|
|
63
|
+
logger.log(`Reopening WebSocket in ${this.constructor.reopenDelay}ms`)
|
|
64
|
+
setTimeout(this.open, this.constructor.reopenDelay)
|
|
65
|
+
}
|
|
66
|
+
} else {
|
|
67
|
+
return this.open()
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
getProtocol() {
|
|
72
|
+
if (this.webSocket) {
|
|
73
|
+
return this.webSocket.protocol
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
isOpen() {
|
|
78
|
+
return this.isState("open")
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
isActive() {
|
|
82
|
+
return this.isState("open", "connecting")
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
triedToReconnect() {
|
|
86
|
+
return this.monitor.reconnectAttempts > 0
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Private
|
|
90
|
+
|
|
91
|
+
isProtocolSupported() {
|
|
92
|
+
return indexOf.call(supportedProtocols, this.getProtocol()) >= 0
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
isState(...states) {
|
|
96
|
+
return indexOf.call(states, this.getState()) >= 0
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
getState() {
|
|
100
|
+
if (this.webSocket) {
|
|
101
|
+
for (let state in adapters.WebSocket) {
|
|
102
|
+
if (adapters.WebSocket[state] === this.webSocket.readyState) {
|
|
103
|
+
return state.toLowerCase()
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
return null
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
installEventHandlers() {
|
|
111
|
+
for (let eventName in this.events) {
|
|
112
|
+
const handler = this.events[eventName].bind(this)
|
|
113
|
+
this.webSocket[`on${eventName}`] = handler
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
uninstallEventHandlers() {
|
|
118
|
+
for (let eventName in this.events) {
|
|
119
|
+
this.webSocket[`on${eventName}`] = function() {}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
Connection.reopenDelay = 500
|
|
126
|
+
|
|
127
|
+
Connection.prototype.events = {
|
|
128
|
+
message(event) {
|
|
129
|
+
if (!this.isProtocolSupported()) { return }
|
|
130
|
+
const {identifier, ids, message, reason, reconnect, type, broadcasting, id} = JSON.parse(event.data)
|
|
131
|
+
this.monitor.recordMessage()
|
|
132
|
+
switch (type) {
|
|
133
|
+
case message_types.welcome:
|
|
134
|
+
if (this.triedToReconnect()) {
|
|
135
|
+
this.reconnectAttempted = true
|
|
136
|
+
}
|
|
137
|
+
this.monitor.recordConnect()
|
|
138
|
+
return this.subscriptions.reload()
|
|
139
|
+
case message_types.disconnect:
|
|
140
|
+
logger.log(`Disconnecting. Reason: ${reason}`)
|
|
141
|
+
return this.close({allowReconnect: reconnect})
|
|
142
|
+
case message_types.history:
|
|
143
|
+
return this.subscriptions.ingestHistory(identifier, broadcasting, message)
|
|
144
|
+
case message_types.ping:
|
|
145
|
+
return null
|
|
146
|
+
case message_types.confirmation:
|
|
147
|
+
this.subscriptions.confirmSubscription(identifier, ids)
|
|
148
|
+
if (this.reconnectAttempted) {
|
|
149
|
+
this.reconnectAttempted = false
|
|
150
|
+
return this.subscriptions.notify(identifier, "connected", {reconnected: true})
|
|
151
|
+
} else {
|
|
152
|
+
return this.subscriptions.notify(identifier, "connected", {reconnected: false})
|
|
153
|
+
}
|
|
154
|
+
case message_types.rejection:
|
|
155
|
+
return this.subscriptions.reject(identifier)
|
|
156
|
+
default:
|
|
157
|
+
return this.subscriptions.receive(identifier, message, id, broadcasting)
|
|
158
|
+
}
|
|
159
|
+
},
|
|
160
|
+
|
|
161
|
+
open() {
|
|
162
|
+
logger.log(`WebSocket onopen event, using '${this.getProtocol()}' subprotocol`)
|
|
163
|
+
this.disconnected = false
|
|
164
|
+
if (!this.isProtocolSupported()) {
|
|
165
|
+
logger.log("Protocol is unsupported. Stopping monitor and disconnecting.")
|
|
166
|
+
return this.close({allowReconnect: false})
|
|
167
|
+
}
|
|
168
|
+
},
|
|
169
|
+
|
|
170
|
+
close(event) {
|
|
171
|
+
logger.log("WebSocket onclose event")
|
|
172
|
+
if (this.disconnected) { return }
|
|
173
|
+
this.disconnected = true
|
|
174
|
+
this.monitor.recordDisconnect()
|
|
175
|
+
return this.subscriptions.notifyAll("disconnected", {willAttemptReconnect: this.monitor.isRunning()})
|
|
176
|
+
},
|
|
177
|
+
|
|
178
|
+
error() {
|
|
179
|
+
logger.log("WebSocket onerror event")
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
export default Connection
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import logger from "./logger"
|
|
2
|
+
|
|
3
|
+
// Responsible for ensuring the cable connection is in good health by validating the heartbeat pings sent from the server, and attempting
|
|
4
|
+
// revival reconnections if things go astray. Internal class, not intended for direct user manipulation.
|
|
5
|
+
|
|
6
|
+
const now = () => new Date().getTime()
|
|
7
|
+
|
|
8
|
+
const secondsSince = time => (now() - time) / 1000
|
|
9
|
+
|
|
10
|
+
class ConnectionMonitor {
|
|
11
|
+
constructor(connection) {
|
|
12
|
+
this.visibilityDidChange = this.visibilityDidChange.bind(this)
|
|
13
|
+
this.connection = connection
|
|
14
|
+
this.reconnectAttempts = 0
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
start() {
|
|
18
|
+
if (!this.isRunning()) {
|
|
19
|
+
this.startedAt = now()
|
|
20
|
+
delete this.stoppedAt
|
|
21
|
+
this.startPolling()
|
|
22
|
+
addEventListener("visibilitychange", this.visibilityDidChange)
|
|
23
|
+
logger.log(`ConnectionMonitor started. stale threshold = ${this.constructor.staleThreshold} s`)
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
stop() {
|
|
28
|
+
if (this.isRunning()) {
|
|
29
|
+
this.stoppedAt = now()
|
|
30
|
+
this.stopPolling()
|
|
31
|
+
removeEventListener("visibilitychange", this.visibilityDidChange)
|
|
32
|
+
logger.log("ConnectionMonitor stopped")
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
isRunning() {
|
|
37
|
+
return this.startedAt && !this.stoppedAt
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
recordMessage() {
|
|
41
|
+
this.pingedAt = now()
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
recordConnect() {
|
|
45
|
+
this.reconnectAttempts = 0
|
|
46
|
+
delete this.disconnectedAt
|
|
47
|
+
logger.log("ConnectionMonitor recorded connect")
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
recordDisconnect() {
|
|
51
|
+
this.disconnectedAt = now()
|
|
52
|
+
logger.log("ConnectionMonitor recorded disconnect")
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Private
|
|
56
|
+
|
|
57
|
+
startPolling() {
|
|
58
|
+
this.stopPolling()
|
|
59
|
+
this.poll()
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
stopPolling() {
|
|
63
|
+
clearTimeout(this.pollTimeout)
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
poll() {
|
|
67
|
+
this.pollTimeout = setTimeout(() => {
|
|
68
|
+
this.reconnectIfStale()
|
|
69
|
+
this.poll()
|
|
70
|
+
}
|
|
71
|
+
, this.getPollInterval())
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
getPollInterval() {
|
|
75
|
+
const { staleThreshold, reconnectionBackoffRate } = this.constructor
|
|
76
|
+
const backoff = Math.pow(1 + reconnectionBackoffRate, Math.min(this.reconnectAttempts, 10))
|
|
77
|
+
const jitterMax = this.reconnectAttempts === 0 ? 1.0 : reconnectionBackoffRate
|
|
78
|
+
const jitter = jitterMax * Math.random()
|
|
79
|
+
return staleThreshold * 1000 * backoff * (1 + jitter)
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
reconnectIfStale() {
|
|
83
|
+
if (this.connectionIsStale()) {
|
|
84
|
+
logger.log(`ConnectionMonitor detected stale connection. reconnectAttempts = ${this.reconnectAttempts}, time stale = ${secondsSince(this.refreshedAt)} s, stale threshold = ${this.constructor.staleThreshold} s`)
|
|
85
|
+
this.reconnectAttempts++
|
|
86
|
+
if (this.disconnectedRecently()) {
|
|
87
|
+
logger.log(`ConnectionMonitor skipping reopening recent disconnect. time disconnected = ${secondsSince(this.disconnectedAt)} s`)
|
|
88
|
+
} else {
|
|
89
|
+
logger.log("ConnectionMonitor reopening")
|
|
90
|
+
this.connection.reopen()
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
get refreshedAt() {
|
|
96
|
+
return this.pingedAt ? this.pingedAt : this.startedAt
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
connectionIsStale() {
|
|
100
|
+
return secondsSince(this.refreshedAt) > this.constructor.staleThreshold
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
disconnectedRecently() {
|
|
104
|
+
return this.disconnectedAt && (secondsSince(this.disconnectedAt) < this.constructor.staleThreshold)
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
visibilityDidChange() {
|
|
108
|
+
if (document.visibilityState === "visible") {
|
|
109
|
+
setTimeout(() => {
|
|
110
|
+
if (this.connectionIsStale() || !this.connection.isOpen()) {
|
|
111
|
+
logger.log(`ConnectionMonitor reopening stale connection on visibilitychange. visibilityState = ${document.visibilityState}`)
|
|
112
|
+
this.connection.reopen()
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
, 200)
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
ConnectionMonitor.staleThreshold = 6 // Server::Connections::BEAT_INTERVAL * 2 (missed two pings)
|
|
122
|
+
ConnectionMonitor.reconnectionBackoffRate = 0.15
|
|
123
|
+
|
|
124
|
+
export default ConnectionMonitor
|