turbo_boost-commands 0.0.18 → 0.1.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.

Potentially problematic release.


This version of turbo_boost-commands might be problematic. Click here for more details.

checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 342917e85cc7c292f5a8291685144003787e2c7160bff7efd99201d4ccf3b79b
4
- data.tar.gz: 1f56a0a3556b021e07cb7431a2322b1aa5b7f410f4a128009d2c78f8d2f8aa4f
3
+ metadata.gz: fbb5115c46ef7a7765c15f8527e9b1738cba5f92c0b1ef6ad3eacf956fef20b1
4
+ data.tar.gz: f01a9ad64ecd2ca37632dc40688ae6d45249eae04e23609e97d61539020258de
5
5
  SHA512:
6
- metadata.gz: 28129732bad9aa2621714b0e3ea7714d2f096075f61594e7d331343ac45a2741db02a9fb849a5355e1b033038bb7a85f6c3b16bd2be7ac8f42e2b14f6ea2093e
7
- data.tar.gz: 3b1088f768fcab89de2bdb4ebf65c3b36d4db675b42b01e0bf3bc16ec445c716f5aafa3cfc00ad8d448249bed00e5bf553cd942e0b9a13a6516a1a1d014b71e3
6
+ metadata.gz: 5a897509728f69a062a805e7814f780bfcfc709d93311573cb5b3883b30b474b9ebf01941bc4ea81720bee19e3fec3e9ea1f5f73f9857606a283ed41fcdd9a70
7
+ data.tar.gz: 1f6f645ce6c9b5e77589dfc2f144273f628d21b62b90ba7e8cf48d23251f335a313a73fc80c1d5caba0032741947160d1b381d5c97e0a3b8bd3eb68be5567a59
data/README.md CHANGED
@@ -8,7 +8,7 @@
8
8
  </h1>
9
9
  <p align="center">
10
10
  <a href="http://blog.codinghorror.com/the-best-code-is-no-code-at-all/">
11
- <img alt="Lines of Code" src="https://img.shields.io/badge/loc-1580-47d299.svg" />
11
+ <img alt="Lines of Code" src="https://img.shields.io/badge/loc-1352-47d299.svg" />
12
12
  </a>
13
13
  <a href="https://codeclimate.com/github/hopsoft/turbo_boost-commands/maintainability">
14
14
  <img src="https://api.codeclimate.com/v1/badges/fe1162a742fe83a4fdfd/maintainability" />
@@ -131,10 +131,12 @@ Commands can be tested in isolation as well as with standard Rails controller, i
131
131
 
132
132
  ## Dependencies
133
133
 
134
- - [rails](https://rubygems.org/gems/rails) `>=6.1`
135
- - [turbo-rails](https://rubygems.org/gems/turbo-rails) `>=1.1`
136
- - [@hotwired/turbo-rails](https://yarnpkg.com/package/@hotwired/turbo-rails) `>=7.1`
137
- - [ruby](https://github.com/ruby/ruby) `>=2.7`
134
+ - [rails](https://rubygems.org/gems/rails) `>= 6.1`
135
+ - [turbo-rails](https://rubygems.org/gems/turbo-rails) `>= 1.1`
136
+ - [@hotwired/turbo-rails](https://www.npmjs.com/package/@hotwired/turbo-rails) `>= 7.2`
137
+ - [alpinejs](https://www.npmjs.com/package/alpinejs) `>= 3.13`
138
+ - [@alpinejs/morph](https://www.npmjs.com/package/@alpinejs/morph) `>= 3.13`
139
+ - [@turbo-boost/streams](https://www.npmjs.com/package/@turbo-boost/streams) `>= 0.1.7`
138
140
 
139
141
  ## Setup
140
142
 
@@ -169,19 +171,6 @@ rails app:template LOCATION='https://railsbytes.com/script/xkjsbB'
169
171
  +import '@turbo-boost/commands'
170
172
  ```
171
173
 
172
- 3. Add TurboBoost to your Rails app
173
-
174
- ```diff
175
- # app/views/layouts/application.html.erb
176
- <html>
177
- <head>
178
- + <%= turbo_boost.meta_tag %>
179
- </head>
180
- <body>
181
- </body>
182
- </html>
183
- ```
184
-
185
174
  ## Usage
186
175
 
187
176
  This example illustrates how to use TurboBoost Commands to manage upvotes on a Post.
@@ -556,14 +545,21 @@ fly deploy
556
545
 
557
546
  ## Releasing
558
547
 
559
- 1. Run `yarn` and `bundle` to pick up the latest
560
- 1. Bump version number at `lib/turbo_boost-streams/version.rb`. Pre-release versions use `.preN`
561
- 1. Bump version number at `package.json` _(make sure it matches)_. Pre-release versions use `-preN`
562
- 1. Run `yarn build` and `rake build`
563
- 1. Commit and push changes to GitHub
548
+ > [!TIP]
549
+ > Run these commands on the host machine _(i.e. not inside the dev container)_
550
+
551
+ 1. Run `npm update` and `bundle update` to pick up the latest dependencies
552
+ 1. Update the version number consistently in the following files:
553
+ * `lib/turbo_boost/commands/version.rb` - pre-release versions should use `.preN`
554
+ * `app/javascript/version.js` - pre-release versions use `-preN`
555
+ * `package.json` - pre-release versions use `-preN`
556
+ 1. Run `bin/standardize`
557
+ 1. Run `rake build`
558
+ 1. Run `npm run build`
559
+ 1. Commit and push any changes to GitHub
564
560
  1. Run `rake release`
565
- 1. Run `yarn publish --no-git-tag-version --access public --new-version X.X.X` _(use same version number)_
566
- 1. Create a new release on GitHub ([here](https://github.com/hopsoft/turbo_boost-streams/releases)) and generate the changelog for the stable release for it
561
+ 1. Run `npm publish --access public`
562
+ 1. Create a new release on GitHub ([here](https://github.com/hopsoft/turbo_boost-commands/releases)) and generate the changelog for the stable release for it
567
563
 
568
564
  ## About TurboBoost
569
565
 
@@ -1,2 +1,2 @@
1
- var Z=Object.defineProperty,ee=Object.defineProperties;var te=Object.getOwnPropertyDescriptors;var I=Object.getOwnPropertySymbols;var re=Object.prototype.hasOwnProperty,oe=Object.prototype.propertyIsEnumerable;var X=(e,t,r)=>t in e?Z(e,t,{enumerable:!0,configurable:!0,writable:!0,value:r}):e[t]=r,s=(e,t)=>{for(var r in t||(t={}))re.call(t,r)&&X(e,r,t[r]);if(I)for(var r of I(t))oe.call(t,r)&&X(e,r,t[r]);return e},u=(e,t)=>ee(e,te(t));var O=class{get element(){return document.querySelector('meta[name="turbo-boost"]')}get token(){return this.element.getAttribute("content")}get busy(){return this.element.dataset.busy==="true"}set busy(t){return this.element.dataset.busy=!!t}},a=new O;var i={start:"turbo-boost:command:start",success:"turbo-boost:command:success",finish:"turbo-boost:command:finish",abort:"turbo-boost:command:abort",clientError:"turbo-boost:command:client-error",serverError:"turbo-boost:command:server-error"},l={stateLoad:"turbo-boost:state:load",stateChange:"turbo-boost:state:change"},f=s(s({},i),l);function d(e,t,r={}){return new Promise(o=>{r=r||{},r.detail=r.detail||{},t=t||document;let n=new CustomEvent(e,u(s({},r),{bubbles:!0}));t.dispatchEvent(n),o(n)})}var B;function k(e,t=null){if(!e||typeof e!="object")return e;let r=new Proxy(e,{deleteProperty(o,n){return delete o[n],d(l.stateChange,a.element,{detail:{state:B}}),!0},set(o,n,c,A){return o[n]=k(c,this),d(l.stateChange,a.element,{detail:{state:B}}),!0}});if(Array.isArray(e))e.forEach((o,n)=>e[n]=k(o,r));else if(typeof e=="object")for(let[o,n]of Object.entries(e))e[o]=k(n,r);return t||(B=r),r}var F=k;var D,v,C,N;function J(){if(!a.element)return g();let e=atob(a.element.dataset.state);C={},v=F(JSON.parse(e)),D=s({},v),delete a.element.dataset.clientStateChange,setTimeout(()=>d(l.stateLoad,a.element,{detail:{state:v}}))}function g(){clearTimeout(N),N=setTimeout(J,10)}D||J();addEventListener("DOMContentLoaded",g);addEventListener("load",g);addEventListener("turbo:load",g);addEventListener("turbo:frame-load",g);addEventListener(i.success,g);addEventListener(l.stateChange,e=>{C={};for(let[t,r]of Object.entries(v))D[t]!==r&&(C[t]=r);a.element.dataset.clientStateChange=!0,a.element.dataset.state=btoa(JSON.stringify(v))});var h={events:l,get current(){return v},get delta(){return C},get payloadChunks(){return btoa(JSON.stringify(C)).match(/.{1,2000}/g)}};function ne(e){let t="<html",r="</html",o=e.indexOf(t),n=e.lastIndexOf(r);if(o>=0&&n>=0){let c=e.slice(e.indexOf(">",o)+1,n);document.documentElement.innerHTML=c}}function se(e){document.body.insertAdjacentHTML("beforeend",e)}var E={append:se,replaceDocument:ne};var L={};function ae(e){L[e.id]=e}function ie(e){delete L[e]}var S={add:ae,remove:ie,get commands(){return[...Object.values(L)]},get length(){return Object.keys(L).length}};function M(e){e.detail.endedAt=Date.now(),e.detail.milliseconds=e.detail.endedAt-e.detail.startedAt,setTimeout(()=>d(i.finish,e.target,{detail:e.detail}),25)}addEventListener(i.serverError,M);addEventListener(i.success,M);addEventListener(i.finish,e=>S.remove(e.detail.id),!0);var T={events:i};var R={};addEventListener("turbo:before-fetch-request",e=>{let t=e.target.closest("turbo-frame"),{fetchOptions:r}=e.detail;if(a.busy){let o=["text/vnd.turbo-boost.html",r.headers.Accept];o=o.filter(n=>n&&n.trim().length>0).join(", "),r.headers.Accept=o,r.headers["TurboBoost-Token"]=a.token}h.payloadChunks.forEach((o,n)=>{r.headers[`TurboBoost-State-${n.toString().padStart(4,"0")}`]=o})});addEventListener("turbo:before-fetch-response",e=>{let t=e.target.closest("turbo-frame"),{fetchResponse:r}=e.detail;if(t&&(R[t.id]=t.src),r.header("TurboBoost")){if(r.statusCode<200||r.statusCode>399){let o=`Server returned a ${r.statusCode} status code! TurboBoost Commands require 2XX-3XX status codes.`;d(T.events.clientError,document,{detail:u(s({},e.detail),{error:o})},!0)}r.header("TurboBoost")==="Append"&&(e.preventDefault(),r.responseText.then(o=>E.append(o)))}});addEventListener("turbo:frame-load",e=>{let t=e.target.closest("turbo-frame");t.dataset.turboBoostSrc=R[t.id]||t.src||t.dataset.turboBoostSrc,delete R[t.id]});var de={frameAttribute:"data-turbo-frame",methodAttribute:"data-turbo-method",commandAttribute:"data-turbo-command",confirmAttribute:"data-turbo-confirm"},m=s({},de);var j={method:e=>Promise.resolve(confirm(e))},me=e=>e.detail.driver==="method",ue=e=>{if(e.detail.driver!=="form")return!1;let t=e.target,r=t.closest("turbo-frame"),o=t.closest(`[${m.frameAttribute}]`);return!!(r||o)},ce=e=>me(e)||ue(e);document.addEventListener(i.start,async e=>{let t=e.target.getAttribute(m.confirmAttribute);if(!t||(e.detail.confirmation=!0,ce(e)))return;await j.method(t)||e.preventDefault()});var W=j;var b=[],$;function le(e,t){let r=b.find(o=>o.name===e);return r&&b.splice(b.indexOf(r),1),b=[{name:e,selectors:t},...b],document.removeEventListener(e,$,!0),document.addEventListener(e,$,!0),s({},b.find(o=>o.name===e))}function fe(e){return b.find(t=>t.selectors.find(r=>Array.from(document.querySelectorAll(r)).find(o=>o===e)))}function be(e,t){let r=fe(t);return r&&r.name===e}var p={register:le,isRegisteredForElement:be,get events(){return[...b]},set handler(e){$=e}};function pe(e){return e.closest(`[${m.commandAttribute}]`)}function he(e){return e.closest("turbo-frame[src]")||e.closest("turbo-frame[data-turbo-frame-src]")||e.closest("turbo-frame")}function ve(e,t={}){if(e.tagName.toLowerCase()!=="select")return t.value=e.value||null;if(!e.multiple)return t.value=e.options[e.selectedIndex].value;t.values=Array.from(e.options).reduce((r,o)=>(o.selected&&r.push(o.value),r),[])}function ge(e){let t=Array.from(e.attributes).reduce((r,o)=>{let n=o.value;return r[o.name]=n,r},{});return t.tag=e.tagName,t.checked=!!e.checked,t.disabled=!!e.disabled,ve(e,t),delete t.class,delete t.action,delete t.href,delete t[m.commandAttribute],delete t[m.frameAttribute],t}var y={buildAttributePayload:ge,findClosestCommand:pe,findClosestFrameWithSource:he};function Ee(e,t={},r={}){t.token=a.token;let o=e.querySelector('input[name="turbo_boost_command"]')||document.createElement("input");o.type="hidden",o.name="turbo_boost_command",o.value=JSON.stringify(t),e.appendChild(o)}var U={invokeCommand:Ee};function xe(e,t={}){let r=document.createElement("a");r.href=e;let o=new URL(r);return o.searchParams.set("turbo_boost_command",JSON.stringify(t)),o}var x={build:xe};function Ce(e,t){let r=t.src;t=s({},t),delete t.src,e.src=x.build(r,t)}var H={invokeCommand:Ce};function Te(e,t={}){let r=t.src;t=s({},t),delete t.src,delete t.href,e.setAttribute("href",x.build(r,t))}var V={invokeCommand:Te};function ye(e){let t=e.target;d(T.events.abort,document,{detail:u(s({},e.detail),{xhr:t})})}function P(e){let t=e.target;(t.getResponseHeader("TurboBoost")==="Append"||t.getResponseHeader("Content-Type").startsWith("text/vnd.turbo-boost.html"))&&E.append(t.responseText);let o=`Server returned a ${t.status} status code! TurboBoost Commands require 2XX-3XX status codes.`;d(T.events.clientError,document,{detail:u(s({},e.detail),{error:o,xhr:t})},!0)}function Ae(e){let t=e.target;if(t.status<200||t.status>399)return P(e);let r=t.responseText;t.getResponseHeader("TurboBoost")==="Append"||t.getResponseHeader("Content-Type").startsWith("text/vnd.turbo-boost.html")?E.append(t.responseText):E.replaceDocument(t.responseText)}function ke(e){let t=e.src;e=s({},e),delete e.src;try{let r=new XMLHttpRequest;r.open("GET",x.build(t,e),!0),r.setRequestHeader("Accept","text/vnd.turbo-boost.html, text/html, application/xhtml+xml"),r.setRequestHeader("TurboBoost-Token",a.token),h.payloadChunks.forEach((o,n)=>r.setRequestHeader(`TurboBoost-State-${n.toString().padStart(4,"0")}`,o)),r.addEventListener("abort",ye),r.addEventListener("error",P),r.addEventListener("load",Ae),r.send()}catch(r){let o=`Unexpected error sending HTTP request! ${r.message}`;P(r,{detail:{message:o}})}}var G={invokeCommand:ke};function q(e,t){return t=t||{dataset:{}},e.href||t.src||t.dataset.turboBoostSrc||location.href}function Le(e){let t=y.findClosestFrameWithSource(e),{turboFrame:r,turboMethod:o}=e.dataset;return e.tagName.toLowerCase()==="form"?{name:"form",reason:"Element is a form.",frame:t,src:e.action,invokeCommand:U.invokeCommand}:o&&o.length>0?{name:"method",reason:"Element defines data-turbo-method.",frame:t,src:e.href,invokeCommand:V.invokeCommand}:r&&r!=="_self"?(t=document.getElementById(r),{name:"frame",reason:"element targets a frame that is not _self",frame:t,src:q(e,t),invokeCommand:H.invokeCommand}):(!r||r==="_self")&&t?{name:"frame",reason:"element does NOT target a frame or targets _self and is contained by a frame",frame:t,src:q(e,t),invokeCommand:H.invokeCommand}:{name:"window",reason:"element matches one or more of the following conditions (targets _top, does NOT target a frame, is NOT contained by a frame)",frame:null,src:q(e),invokeCommand:G.invokeCommand}}var _={find:Le};var w="unknown",z={debug:Object.values(f),info:Object.values(f),warn:[f.abort,f.clientError,f.serverError],error:[f.clientError,f.serverError],unknown:[]};Object.values(f).forEach(e=>{addEventListener(e,t=>{if(z[w].includes(t.type)){let{target:r,detail:o}=t;console[w](t.type,{target:r,detail:o})}})});var K={get level(){return w},set level(e){return Object.keys(z).includes(e)||(e="unknown"),w=e}};function Se(){return("10000000-1000-4000-8000"+-1e11).replace(/[018]/g,e=>(e^crypto.getRandomValues(new Uint8Array(1))[0]&15>>e/4).toString(16))}var Q={v4:Se};function Y(e,t){return{id:e,name:t.getAttribute(m.commandAttribute),elementId:t.id.length>0?t.id:null,elementAttributes:y.buildAttributePayload(t),startedAt:Date.now()}}async function we(e){let t,r={};try{if(t=y.findClosestCommand(e.target),!t||!p.isRegisteredForElement(e.type,t))return;let o=`turbo-command-${Q.v4()}`,n=_.find(t),c=u(s({},Y(o,t)),{driver:n.name,frameId:n.frame?n.frame.id:null,src:n.src}),A=await d(i.start,t,{cancelable:!0,detail:c});if(A.defaultPrevented||A.detail.confirmation&&e.defaultPrevented)return d(i.abort,t,{detail:{message:`An event handler for '${i.start}' prevented default behavior and blocked command invocation!`,source:A}});switch(n=_.find(t),c=u(s({},Y(o,t)),{driver:n.name,frameId:n.frame?n.frame.id:null,src:n.src}),S.add(c),["frame","window"].includes(n.name)&&e.preventDefault(),a.busy=!0,setTimeout(()=>a.busy=!1,10),n.name){case"method":return n.invokeCommand(t,c);case"form":return n.invokeCommand(t,c,e);case"frame":return n.invokeCommand(n.frame,c);case"window":return n.invokeCommand(c)}}catch(o){d(i.clientError,t,{detail:u(s({},r),{error:o})})}}self.TurboBoost=self.TurboBoost||{};self.TurboBoost=u(s({},self.TurboBoost),{stateEvents:l,get state(){return h.current},get stateDelta(){return h.delta}});self.TurboBoost.Commands||(p.handler=we,p.register("click",[`[${m.commandAttribute}]`]),p.register("submit",[`form[${m.commandAttribute}]`]),p.register("change",[`input[${m.commandAttribute}]`,`select[${m.commandAttribute}]`,`textarea[${m.commandAttribute}]`]),self.TurboBoost.Commands={confirmation:W,logger:K,schema:m,events:i,registerEventDelegate:p.register,get eventDelegates(){return p.events}});var Qt=self.TurboBoost.Commands;export{Qt as default};
1
+ var Q=Object.defineProperty,Y=Object.defineProperties;var Z=Object.getOwnPropertyDescriptors;var I=Object.getOwnPropertySymbols;var ee=Object.prototype.hasOwnProperty,te=Object.prototype.propertyIsEnumerable;var X=(e,t,r)=>t in e?Q(e,t,{enumerable:!0,configurable:!0,writable:!0,value:r}):e[t]=r,s=(e,t)=>{for(var r in t||(t={}))ee.call(t,r)&&X(e,r,t[r]);if(I)for(var r of I(t))te.call(t,r)&&X(e,r,t[r]);return e},c=(e,t)=>Y(e,Z(t));var d={start:"turbo-boost:command:start",success:"turbo-boost:command:success",finish:"turbo-boost:command:finish",abort:"turbo-boost:command:abort",clientError:"turbo-boost:command:client-error",serverError:"turbo-boost:command:server-error"},f={stateLoad:"turbo-boost:state:load",stateChange:"turbo-boost:state:change"},u=s(s({},d),f);function a(e,t,r={}){return new Promise(o=>{r=r||{},r.detail=r.detail||{},t=t||document;let n=new CustomEvent(e,c(s({},r),{bubbles:!0}));t.dispatchEvent(n),o(n)})}var L;function C(e,t=null){if(!e||typeof e!="object")return e;let r=new Proxy(e,{deleteProperty(o,n){return delete o[n],a(f.stateChange,document,{detail:{state:L}}),!0},set(o,n,i,b){return o[n]=C(i,this),a(f.stateChange,document,{detail:{state:L}}),!0}});if(Array.isArray(e))e.forEach((o,n)=>e[n]=C(o,r));else if(typeof e=="object")for(let[o,n]of Object.entries(e))e[o]=C(n,r);return t||(L=r),r}var _=C;var S,A,O,q;function re(e,t){let r=JSON.parse(e);S=s({},r),q=t,A=_(r),O={},setTimeout(()=>a(f.stateLoad,document,{detail:{state:A}}))}addEventListener(f.stateChange,e=>{for(let[t,r]of Object.entries(A))S[t]!==r&&(O[t]=r)});var y={initialize:re,events:f,get initial(){return S},get current(){return A},get changed(){return O},get signed(){return q}};function oe(e){let t="<html",r="</html",o=e.indexOf(t),n=e.lastIndexOf(r);if(o>=0&&n>=0){let i=e.slice(e.indexOf(">",o)+1,n);document.documentElement.innerHTML=i}}function ne(e){document.body.insertAdjacentHTML("beforeend",e)}var h={append:ne,replaceDocument:oe};var T={};function se(e){T[e.id]=e}function ae(e){delete T[e]}var k={add:se,remove:ae,get commands(){return[...Object.values(T)]},get length(){return Object.keys(T).length}};function F(e){e.detail.endedAt=Date.now(),e.detail.milliseconds=e.detail.endedAt-e.detail.startedAt,setTimeout(()=>a(d.finish,e.target,{detail:e.detail}),25)}addEventListener(d.serverError,F);addEventListener(d.success,F);addEventListener(d.finish,e=>k.remove(e.detail.id),!0);var g={events:d};var B={};addEventListener("turbo:before-fetch-request",e=>{var o,n;let t=e.target.closest("turbo-frame"),{fetchOptions:r}=e.detail;if((n=(o=self.TurboBoost)==null?void 0:o.Commands)!=null&&n.busy){let i=["text/vnd.turbo-boost.html",r.headers.Accept];i=i.filter(b=>b&&b.trim().length>0).join(", "),r.headers.Accept=i}});addEventListener("turbo:before-fetch-response",e=>{let t=e.target.closest("turbo-frame"),{fetchResponse:r}=e.detail;if(t&&(B[t.id]=t.src),r.header("TurboBoost")){if(r.statusCode<200||r.statusCode>399){let o=`Server returned a ${r.statusCode} status code! TurboBoost Commands require 2XX-3XX status codes.`;a(g.events.clientError,document,{detail:c(s({},e.detail),{error:o})},!0)}r.header("TurboBoost")==="Append"&&(e.preventDefault(),r.responseText.then(o=>h.append(o)))}});addEventListener("turbo:frame-load",e=>{let t=e.target.closest("turbo-frame");t.dataset.turboBoostSrc=B[t.id]||t.src||t.dataset.turboBoostSrc,delete B[t.id]});var ie={frameAttribute:"data-turbo-frame",methodAttribute:"data-turbo-method",commandAttribute:"data-turbo-command",confirmAttribute:"data-turbo-confirm"},m=s({},ie);var N={method:e=>Promise.resolve(confirm(e))},de=e=>e.detail.driver==="method",me=e=>{if(e.detail.driver!=="form")return!1;let t=e.target,r=t.closest("turbo-frame"),o=t.closest(`[${m.frameAttribute}]`);return!!(r||o)},ce=e=>de(e)||me(e);document.addEventListener(d.start,async e=>{let t=e.target.getAttribute(m.confirmAttribute);if(!t||(e.detail.confirmation=!0,ce(e)))return;await N.method(t)||e.preventDefault()});var M=N;var l=[],D;function ue(e,t){let r=l.find(o=>o.name===e);return r&&l.splice(l.indexOf(r),1),l=[{name:e,selectors:t},...l],document.removeEventListener(e,D,!0),document.addEventListener(e,D,!0),s({},l.find(o=>o.name===e))}function fe(e){return l.find(t=>t.selectors.find(r=>Array.from(document.querySelectorAll(r)).find(o=>o===e)))}function le(e,t){let r=fe(t);return r&&r.name===e}var p={register:ue,isRegisteredForElement:le,get events(){return[...l]},set handler(e){D=e}};function pe(e){return e.closest(`[${m.commandAttribute}]`)}function be(e){return e.closest("turbo-frame[src]")||e.closest("turbo-frame[data-turbo-frame-src]")||e.closest("turbo-frame")}function he(e,t={}){if(e.tagName.toLowerCase()!=="select")return t.value=e.value||null;if(!e.multiple)return t.value=e.options[e.selectedIndex].value;t.values=Array.from(e.options).reduce((r,o)=>(o.selected&&r.push(o.value),r),[])}function ve(e){let t=Array.from(e.attributes).reduce((r,o)=>{let n=o.value;return r[o.name]=n,r},{});return t.tag=e.tagName,t.checked=!!e.checked,t.disabled=!!e.disabled,he(e,t),delete t.class,delete t.action,delete t.href,delete t[m.commandAttribute],delete t[m.frameAttribute],t}var E={buildAttributePayload:ve,findClosestCommand:pe,findClosestFrameWithSource:be};function ge(e,t={},r={}){let o=e.querySelector('input[name="turbo_boost_command"]')||document.createElement("input");o.type="hidden",o.name="turbo_boost_command",o.value=JSON.stringify(t),e.appendChild(o)}var j={invokeCommand:ge};function Ee(e,t={}){let r=document.createElement("a");r.href=e;let o=new URL(r);return o.searchParams.set("tbc",JSON.stringify(t)),o}var v={build:Ee};function xe(e,t){let r=t.src;t=s({},t),delete t.src,e.src=v.build(r,t)}var R={invokeCommand:xe};function Ce(e,t={}){let r=t.src;t=s({},t),delete t.src,delete t.href,e.setAttribute("href",v.build(r,t))}var W={invokeCommand:Ce};function Ae(e){let t=e.target;a(g.events.abort,document,{detail:c(s({},e.detail),{xhr:t})})}function P(e){let t=e.target;(t.getResponseHeader("TurboBoost")==="Append"||t.getResponseHeader("Content-Type").startsWith("text/vnd.turbo-boost.html"))&&h.append(t.responseText);let o=`Server returned a ${t.status} status code! TurboBoost Commands require 2XX-3XX status codes.`;a(g.events.clientError,document,{detail:c(s({},e.detail),{error:o,xhr:t})},!0)}function ye(e){let t=e.target;if(t.status<200||t.status>399)return P(e);let r=t.responseText;t.getResponseHeader("TurboBoost")==="Append"||t.getResponseHeader("Content-Type").startsWith("text/vnd.turbo-boost.html")?h.append(t.responseText):h.replaceDocument(t.responseText)}function Te(e){let t=e.src;e=s({},e),delete e.src;try{let r=new XMLHttpRequest;r.open("GET",v.build(t,e),!0),r.setRequestHeader("Accept","text/vnd.turbo-boost.html, text/html, application/xhtml+xml"),r.addEventListener("abort",Ae),r.addEventListener("error",P),r.addEventListener("load",ye),r.send()}catch(r){let o=`Unexpected error sending HTTP request! ${r.message}`;P(r,{detail:{message:o}})}}var J={invokeCommand:Te};function $(e,t){return t=t||{dataset:{}},e.href||t.src||t.dataset.turboBoostSrc||location.href}function ke(e){let t=E.findClosestFrameWithSource(e),{turboFrame:r,turboMethod:o}=e.dataset;return e.tagName.toLowerCase()==="form"?{name:"form",reason:"Element is a form.",frame:t,src:e.action,invokeCommand:j.invokeCommand}:o&&o.length>0?{name:"method",reason:"Element defines data-turbo-method.",frame:t,src:e.href,invokeCommand:W.invokeCommand}:r&&r!=="_self"?(t=document.getElementById(r),{name:"frame",reason:"element targets a frame that is not _self",frame:t,src:$(e,t),invokeCommand:R.invokeCommand}):(!r||r==="_self")&&t?{name:"frame",reason:"element does NOT target a frame or targets _self and is contained by a frame",frame:t,src:$(e,t),invokeCommand:R.invokeCommand}:{name:"window",reason:"element matches one or more of the following conditions (targets _top, does NOT target a frame, is NOT contained by a frame)",frame:null,src:$(e),invokeCommand:J.invokeCommand}}var H={find:ke};var w="unknown",U={debug:Object.values(u),info:Object.values(u),warn:[u.abort,u.clientError,u.serverError],error:[u.clientError,u.serverError],unknown:[]};Object.values(u).forEach(e=>{addEventListener(e,t=>{if(U[w].includes(t.type)){let{target:r,detail:o}=t;console[w](t.type,{target:r,detail:o})}})});var V={get level(){return w},set level(e){return Object.keys(U).includes(e)||(e="unknown"),w=e}};function we(){return("10000000-1000-4000-8000"+-1e11).replace(/[018]/g,e=>(e^crypto.getRandomValues(new Uint8Array(1))[0]&15>>e/4).toString(16))}var z={v4:we};var G="0.1.1";var Le=self.TurboBoost||{},x={VERSION:G,busy:!1,confirmation:M,logger:V,schema:m,events:d,registerEventDelegate:p.register,get eventDelegates(){return p.events}};function K(e,t){return{id:e,name:t.getAttribute(m.commandAttribute),elementId:t.id.length>0?t.id:null,elementAttributes:E.buildAttributePayload(t),startedAt:Date.now(),token:x.token,signedState:y.signed,clientState:y.changed}}async function Se(e){let t,r={};try{if(t=E.findClosestCommand(e.target),!t||!p.isRegisteredForElement(e.type,t))return;let o=`turbo-command-${z.v4()}`,n=H.find(t),i=c(s({},K(o,t)),{driver:n.name,frameId:n.frame?n.frame.id:null,src:n.src}),b=await a(d.start,t,{cancelable:!0,detail:i});if(b.defaultPrevented||b.detail.confirmation&&e.defaultPrevented)return a(d.abort,t,{detail:{message:`An event handler for '${d.start}' prevented default behavior and blocked command invocation!`,source:b}});switch(n=H.find(t),i=c(s({},K(o,t)),{driver:n.name,frameId:n.frame?n.frame.id:null,src:n.src}),k.add(i),["frame","window"].includes(n.name)&&e.preventDefault(),x.busy=!0,setTimeout(()=>x.busy=!1,10),n.name){case"method":return n.invokeCommand(t,i);case"form":return n.invokeCommand(t,i,e);case"frame":return n.invokeCommand(n.frame,i);case"window":return n.invokeCommand(i)}}catch(o){a(d.clientError,t,{detail:c(s({},r),{error:o})})}}self.TurboBoost=s({},Le);self.TurboBoost.Commands||(p.handler=Se,p.register("click",[`[${m.commandAttribute}]`]),p.register("submit",[`form[${m.commandAttribute}]`]),p.register("change",[`input[${m.commandAttribute}]`,`select[${m.commandAttribute}]`,`textarea[${m.commandAttribute}]`]),self.TurboBoost.Commands=x,self.TurboBoost.State=y);var Gt=x;export{Gt as default};
2
2
  //# sourceMappingURL=commands.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../../../javascript/meta.js", "../../../javascript/events.js", "../../../javascript/state/observable.js", "../../../javascript/state/index.js", "../../../javascript/renderer.js", "../../../javascript/activity.js", "../../../javascript/lifecycle.js", "../../../javascript/turbo.js", "../../../javascript/schema.js", "../../../javascript/confirmation.js", "../../../javascript/delegates.js", "../../../javascript/elements.js", "../../../javascript/drivers/form.js", "../../../javascript/urls.js", "../../../javascript/drivers/frame.js", "../../../javascript/drivers/method.js", "../../../javascript/drivers/window.js", "../../../javascript/drivers/index.js", "../../../javascript/logger.js", "../../../javascript/uuids.js", "../../../javascript/index.js"],
4
- "sourcesContent": ["class Meta {\n get element() {\n return document.querySelector('meta[name=\"turbo-boost\"]')\n }\n\n get token() {\n return this.element.getAttribute('content')\n }\n\n get busy() {\n return this.element.dataset.busy === 'true'\n }\n\n set busy(value) {\n return (this.element.dataset.busy = !!value)\n }\n}\n\nexport default new Meta()\n", "export const commandEvents = {\n start: 'turbo-boost:command:start',\n success: 'turbo-boost:command:success',\n finish: 'turbo-boost:command:finish',\n abort: 'turbo-boost:command:abort',\n clientError: 'turbo-boost:command:client-error',\n serverError: 'turbo-boost:command:server-error'\n}\n\nexport const stateEvents = {\n stateLoad: 'turbo-boost:state:load',\n stateChange: 'turbo-boost:state:change'\n}\n\nexport const allEvents = { ...commandEvents, ...stateEvents }\n\nexport function dispatch(name, target, options = {}) {\n return new Promise(resolve => {\n options = options || {}\n options.detail = options.detail || {}\n target = target || document\n const evt = new CustomEvent(name, { ...options, bubbles: true })\n target.dispatchEvent(evt)\n resolve(evt)\n })\n}\n", "import meta from '../meta'\nimport { dispatch, stateEvents as events } from '../events'\n\nlet head\n\nfunction observable(object, parent = null) {\n if (!object || typeof object !== 'object') return object\n\n const proxy = new Proxy(object, {\n deleteProperty(target, key) {\n delete target[key]\n dispatch(events.stateChange, meta.element, { detail: { state: head } })\n return true\n },\n\n set(target, key, value, receiver) {\n target[key] = observable(value, this)\n dispatch(events.stateChange, meta.element, { detail: { state: head } })\n return true\n }\n })\n\n if (Array.isArray(object)) {\n object.forEach((value, index) => (object[index] = observable(value, proxy)))\n } else if (typeof object === 'object') {\n for (const [key, value] of Object.entries(object)) object[key] = observable(value, proxy)\n }\n\n if (!parent) head = proxy\n return proxy\n}\n\nexport default observable\n", "import meta from '../meta'\nimport observable from './observable'\nimport { dispatch, commandEvents, stateEvents } from '../events'\n\nlet loadedState, currentState, changedState\nlet loadStateTimeout\n\nfunction loadState() {\n if (!meta.element) return loadStateLater()\n const json = atob(meta.element.dataset.state)\n changedState = {}\n currentState = observable(JSON.parse(json))\n loadedState = { ...currentState }\n delete meta.element.dataset.clientStateChange\n setTimeout(() =>\n dispatch(stateEvents.stateLoad, meta.element, {\n detail: { state: currentState }\n })\n )\n}\n\nfunction loadStateLater() {\n clearTimeout(loadStateTimeout)\n loadStateTimeout = setTimeout(loadState, 10)\n}\n\nif (!loadedState) loadState()\n\naddEventListener('DOMContentLoaded', loadStateLater)\naddEventListener('load', loadStateLater)\naddEventListener('turbo:load', loadStateLater)\naddEventListener('turbo:frame-load', loadStateLater)\naddEventListener(commandEvents.success, loadStateLater)\n\naddEventListener(stateEvents.stateChange, event => {\n changedState = {}\n for (const [key, value] of Object.entries(currentState))\n if (loadedState[key] !== value) changedState[key] = value\n meta.element.dataset.clientStateChange = true\n meta.element.dataset.state = btoa(JSON.stringify(currentState))\n})\n\nexport default {\n events: stateEvents,\n\n get current() {\n return currentState\n },\n\n get delta() {\n return changedState\n },\n\n // The UI state changes are split into chunks and sent to the server in an HTTP request header.\n // Max size for an HTTP header is around 4k or 4,000 bytes.\n // A Base64 character is an 8-bit-padded ASCII character... or 1 byte\n //\n // SEE: lib/state.rb - for info on how `state` is serialized/deserialized\n get payloadChunks() {\n return btoa(JSON.stringify(changedState)).match(/.{1,2000}/g)\n }\n}\n", "function replaceDocument(content) {\n const head = '<html'\n const tail = '</html'\n const headIndex = content.indexOf(head)\n const tailIndex = content.lastIndexOf(tail)\n if (headIndex >= 0 && tailIndex >= 0) {\n const html = content.slice(content.indexOf('>', headIndex) + 1, tailIndex)\n document.documentElement.innerHTML = html\n }\n}\n\nfunction append(content) {\n document.body.insertAdjacentHTML('beforeend', content)\n}\n\nexport default { append, replaceDocument }\n", "const active = {}\n\nfunction add(payload) {\n active[payload.id] = payload\n}\n\nfunction remove(id) {\n delete active[id]\n}\n\nexport default {\n add,\n remove,\n get commands() {\n return [...Object.values(active)]\n },\n get length() {\n return Object.keys(active).length\n }\n}\n", "import activity from './activity'\nimport { dispatch, commandEvents } from './events'\n\nfunction finish(event) {\n event.detail.endedAt = Date.now()\n event.detail.milliseconds = event.detail.endedAt - event.detail.startedAt\n setTimeout(() => dispatch(commandEvents.finish, event.target, { detail: event.detail }), 25)\n}\n\n// TODO: forward source event to finish (error or success)\naddEventListener(commandEvents.serverError, finish)\naddEventListener(commandEvents.success, finish)\naddEventListener(commandEvents.finish, event => activity.remove(event.detail.id), true)\n\nexport default { events: commandEvents }\n", "import meta from './meta'\nimport state from './state'\nimport renderer from './renderer'\nimport { dispatch } from './events'\nimport lifecycle from './lifecycle'\n\nconst frameSources = {}\n\n// fires before making a turbo HTTP request\naddEventListener('turbo:before-fetch-request', event => {\n const frame = event.target.closest('turbo-frame')\n const { fetchOptions } = event.detail\n\n // command invoked and busy\n if (meta.busy) {\n let acceptHeaders = ['text/vnd.turbo-boost.html', fetchOptions.headers['Accept']]\n acceptHeaders = acceptHeaders.filter(entry => entry && entry.trim().length > 0).join(', ')\n fetchOptions.headers['Accept'] = acceptHeaders\n fetchOptions.headers['TurboBoost-Token'] = meta.token\n }\n\n // always send state\n state.payloadChunks.forEach((chunk, i) => {\n fetchOptions.headers[`TurboBoost-State-${i.toString().padStart(4, '0')}`] = chunk\n })\n})\n\n// fires after receiving a turbo HTTP response\naddEventListener('turbo:before-fetch-response', event => {\n const frame = event.target.closest('turbo-frame')\n const { fetchResponse: response } = event.detail\n\n if (frame) frameSources[frame.id] = frame.src\n\n if (response.header('TurboBoost')) {\n if (response.statusCode < 200 || response.statusCode > 399) {\n const error = `Server returned a ${response.statusCode} status code! TurboBoost Commands require 2XX-3XX status codes.`\n dispatch(lifecycle.events.clientError, document, { detail: { ...event.detail, error } }, true)\n }\n\n if (response.header('TurboBoost') === 'Append') {\n event.preventDefault()\n response.responseText.then(content => renderer.append(content))\n }\n }\n})\n\n// fires when a frame element is navigated and finishes loading\naddEventListener('turbo:frame-load', event => {\n const frame = event.target.closest('turbo-frame')\n frame.dataset.turboBoostSrc = frameSources[frame.id] || frame.src || frame.dataset.turboBoostSrc\n delete frameSources[frame.id]\n})\n", "const schema = {\n // attributes\n frameAttribute: 'data-turbo-frame',\n methodAttribute: 'data-turbo-method',\n commandAttribute: 'data-turbo-command',\n confirmAttribute: 'data-turbo-confirm'\n}\n\nexport default { ...schema }\n", "import { commandEvents } from './events'\nimport schema from './schema'\n\nconst confirmation = {\n method: message => Promise.resolve(confirm(message))\n}\n\nconst isTurboMethod = event => event.detail.driver === 'method'\n\nconst isTurboForm = event => {\n if (event.detail.driver !== 'form') return false\n\n const element = event.target\n const frame = element.closest('turbo-frame')\n const target = element.closest(`[${schema.frameAttribute}]`)\n return !!(frame || target)\n}\n\nconst shouldDelegate = event => isTurboMethod(event) || isTurboForm(event)\n\ndocument.addEventListener(commandEvents.start, async event => {\n const message = event.target.getAttribute(schema.confirmAttribute)\n if (!message) return\n\n event.detail.confirmation = true\n\n if (shouldDelegate(event)) return // delegate confirmation handling to Turbo\n\n const proceed = await confirmation.method(message)\n if (!proceed) event.preventDefault()\n})\n\nexport default confirmation\n", "let events = []\nlet eventListener\n\nfunction register(eventName, selectors) {\n const match = events.find(evt => evt.name === eventName)\n if (match) events.splice(events.indexOf(match), 1)\n events = [{ name: eventName, selectors }, ...events]\n\n document.removeEventListener(eventName, eventListener, true)\n document.addEventListener(eventName, eventListener, true)\n\n return { ...events.find(evt => evt.name === eventName) }\n}\n\nfunction getRegisteredEventForElement(element) {\n return events.find(evt =>\n evt.selectors.find(selector => Array.from(document.querySelectorAll(selector)).find(el => el === element))\n )\n}\n\nfunction isRegisteredForElement(eventName, element) {\n const evt = getRegisteredEventForElement(element)\n return evt && evt.name === eventName\n}\n\nexport default {\n register,\n isRegisteredForElement,\n get events() {\n return [...events]\n },\n set handler(fn) {\n eventListener = fn\n }\n}\n", "import schema from './schema'\nimport lifecycle from './lifecycle'\n\nfunction findClosestCommand(element) {\n return element.closest(`[${schema.commandAttribute}]`)\n}\n\nfunction findClosestFrameWithSource(element) {\n return (\n element.closest('turbo-frame[src]') ||\n element.closest('turbo-frame[data-turbo-frame-src]') ||\n element.closest('turbo-frame')\n )\n}\n\nfunction assignElementValueToPayload(element, payload = {}) {\n if (element.tagName.toLowerCase() !== 'select') return (payload.value = element.value || null)\n\n if (!element.multiple) return (payload.value = element.options[element.selectedIndex].value)\n\n payload.values = Array.from(element.options).reduce((memo, option) => {\n if (option.selected) memo.push(option.value)\n return memo\n }, [])\n}\n\nfunction buildAttributePayload(element) {\n const payload = Array.from(element.attributes).reduce((memo, attr) => {\n let value = attr.value\n memo[attr.name] = value\n return memo\n }, {})\n\n payload.tag = element.tagName\n payload.checked = !!element.checked\n payload.disabled = !!element.disabled\n assignElementValueToPayload(element, payload)\n\n // reduce payload size to keep URL length smaller\n delete payload.class\n delete payload.action\n delete payload.href\n delete payload[schema.commandAttribute]\n delete payload[schema.frameAttribute]\n\n return payload\n}\n\nexport default {\n buildAttributePayload,\n findClosestCommand,\n findClosestFrameWithSource\n}\n", "import meta from '../meta'\n\nfunction invokeCommand(form, payload = {}, event = {}) {\n payload.token = meta.token\n const input = form.querySelector('input[name=\"turbo_boost_command\"]') || document.createElement('input')\n input.type = 'hidden'\n input.name = 'turbo_boost_command'\n input.value = JSON.stringify(payload)\n form.appendChild(input)\n}\n\nexport default { invokeCommand }\n", "function build(urlString, payload = {}) {\n const a = document.createElement('a')\n a.href = urlString\n const url = new URL(a)\n url.searchParams.set('turbo_boost_command', JSON.stringify(payload))\n return url\n}\n\nexport default { build }\n", "import urls from '../urls'\n\nfunction invokeCommand(frame, payload) {\n const src = payload.src\n payload = { ...payload }\n delete payload.src\n frame.src = urls.build(src, payload)\n}\n\nexport default { invokeCommand }\n", "import urls from '../urls'\n\nfunction invokeCommand(element, payload = {}) {\n const src = payload.src\n payload = { ...payload }\n delete payload.src\n delete payload.href\n element.setAttribute('href', urls.build(src, payload))\n}\n\nexport default { invokeCommand }\n", "import meta from '../meta'\nimport state from '../state'\nimport { dispatch } from '../events'\nimport lifecycle from '../lifecycle'\nimport urls from '../urls'\nimport renderer from '../renderer'\n\nfunction aborted(event) {\n const xhr = event.target\n dispatch(lifecycle.events.abort, document, {\n detail: { ...event.detail, xhr }\n })\n}\n\nfunction errored(event) {\n const xhr = event.target\n\n const append =\n xhr.getResponseHeader('TurboBoost') === 'Append' ||\n xhr.getResponseHeader('Content-Type').startsWith('text/vnd.turbo-boost.html')\n\n if (append) renderer.append(xhr.responseText)\n\n const error = `Server returned a ${xhr.status} status code! TurboBoost Commands require 2XX-3XX status codes.`\n\n dispatch(lifecycle.events.clientError, document, { detail: { ...event.detail, error, xhr } }, true)\n}\n\nfunction loaded(event) {\n const xhr = event.target\n if (xhr.status < 200 || xhr.status > 399) return errored(event)\n const content = xhr.responseText\n const append =\n xhr.getResponseHeader('TurboBoost') === 'Append' ||\n xhr.getResponseHeader('Content-Type').startsWith('text/vnd.turbo-boost.html')\n append ? renderer.append(xhr.responseText) : renderer.replaceDocument(xhr.responseText)\n}\n\nfunction invokeCommand(payload) {\n const src = payload.src\n payload = { ...payload }\n delete payload.src\n\n try {\n const xhr = new XMLHttpRequest()\n xhr.open('GET', urls.build(src, payload), true)\n xhr.setRequestHeader('Accept', 'text/vnd.turbo-boost.html, text/html, application/xhtml+xml')\n xhr.setRequestHeader('TurboBoost-Token', meta.token)\n state.payloadChunks.forEach((chunk, i) =>\n xhr.setRequestHeader(`TurboBoost-State-${i.toString().padStart(4, '0')}`, chunk)\n )\n\n xhr.addEventListener('abort', aborted)\n xhr.addEventListener('error', errored)\n xhr.addEventListener('load', loaded)\n xhr.send()\n } catch (ex) {\n const message = `Unexpected error sending HTTP request! ${ex.message}`\n errored(ex, { detail: { message } })\n }\n}\n\nexport default { invokeCommand }\n", "import elements from '../elements'\nimport formDriver from './form'\nimport frameDriver from './frame'\nimport methodDriver from './method'\nimport windowDriver from './window'\n\nfunction src(element, frame) {\n frame = frame || { dataset: {} }\n return element.href || frame.src || frame.dataset.turboBoostSrc || location.href\n}\n\nfunction find(element) {\n let frame = elements.findClosestFrameWithSource(element)\n\n const { turboFrame, turboMethod } = element.dataset\n\n if (element.tagName.toLowerCase() === 'form')\n return {\n name: 'form',\n reason: 'Element is a form.',\n frame,\n src: element.action,\n invokeCommand: formDriver.invokeCommand\n }\n\n if (turboMethod && turboMethod.length > 0)\n return {\n name: 'method',\n reason: 'Element defines data-turbo-method.',\n frame,\n src: element.href,\n invokeCommand: methodDriver.invokeCommand\n }\n\n // element targets a frame that is not _self\n if (turboFrame && turboFrame !== '_self') {\n frame = document.getElementById(turboFrame)\n return {\n name: 'frame',\n reason: 'element targets a frame that is not _self',\n frame,\n src: src(element, frame),\n invokeCommand: frameDriver.invokeCommand\n }\n }\n\n // element does NOT target a frame or targets _self and is contained by a frame\n if ((!turboFrame || turboFrame === '_self') && frame)\n return {\n name: 'frame',\n reason: 'element does NOT target a frame or targets _self and is contained by a frame',\n frame,\n src: src(element, frame),\n invokeCommand: frameDriver.invokeCommand\n }\n\n // element matches one or more of the following conditions\n // - targets _top\n // - does NOT target a frame\n // - is NOT contained by a frame\n return {\n name: 'window',\n reason:\n 'element matches one or more of the following conditions (targets _top, does NOT target a frame, is NOT contained by a frame)',\n frame: null,\n src: src(element),\n invokeCommand: windowDriver.invokeCommand\n }\n}\n\nexport default { find }\n", "import { allEvents as events } from './events'\n\nlet currentLevel = 'unknown'\n\nconst logLevels = {\n debug: Object.values(events),\n info: Object.values(events),\n warn: [events.abort, events.clientError, events.serverError],\n error: [events.clientError, events.serverError],\n unknown: []\n}\n\nObject.values(events).forEach(name => {\n addEventListener(name, event => {\n if (logLevels[currentLevel].includes(event.type)) {\n const { target, detail } = event\n console[currentLevel](event.type, { target, detail })\n }\n })\n})\n\nexport default {\n get level() {\n return currentLevel\n },\n set level(value) {\n if (!Object.keys(logLevels).includes(value)) value = 'unknown'\n return (currentLevel = value)\n }\n}\n", "function v4() {\n return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, c =>\n (c ^ (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (c / 4)))).toString(16)\n )\n}\n\nexport default { v4 }\n", "import './turbo'\nimport schema from './schema'\nimport { dispatch, commandEvents, stateEvents } from './events'\nimport activity from './activity'\nimport confirmation from './confirmation'\nimport delegates from './delegates'\nimport drivers from './drivers'\nimport meta from './meta'\nimport elements from './elements'\nimport lifecycle from './lifecycle'\nimport logger from './logger'\nimport state from './state'\nimport urls from './urls'\nimport uuids from './uuids'\n\nfunction buildCommandPayload(id, element) {\n return {\n id, // uniquely identifies the command\n name: element.getAttribute(schema.commandAttribute),\n elementId: element.id.length > 0 ? element.id : null,\n elementAttributes: elements.buildAttributePayload(element),\n startedAt: Date.now()\n }\n}\n\nasync function invokeCommand(event) {\n let element\n let payload = {}\n\n try {\n element = elements.findClosestCommand(event.target)\n if (!element) return\n if (!delegates.isRegisteredForElement(event.type, element)) return\n\n const commandId = `turbo-command-${uuids.v4()}`\n let driver = drivers.find(element)\n let payload = {\n ...buildCommandPayload(commandId, element),\n driver: driver.name,\n frameId: driver.frame ? driver.frame.id : null,\n src: driver.src\n }\n\n const startEvent = await dispatch(commandEvents.start, element, {\n cancelable: true,\n detail: payload\n })\n\n if (startEvent.defaultPrevented || (startEvent.detail.confirmation && event.defaultPrevented))\n return dispatch(commandEvents.abort, element, {\n detail: {\n message: `An event handler for '${commandEvents.start}' prevented default behavior and blocked command invocation!`,\n source: startEvent\n }\n })\n\n // the element and thus the driver may have changed based on the start event handler(s)\n driver = drivers.find(element)\n payload = {\n ...buildCommandPayload(commandId, element),\n driver: driver.name,\n frameId: driver.frame ? driver.frame.id : null,\n src: driver.src\n }\n\n activity.add(payload)\n\n if (['frame', 'window'].includes(driver.name)) event.preventDefault()\n\n meta.busy = true\n setTimeout(() => (meta.busy = false), 10)\n\n switch (driver.name) {\n case 'method':\n return driver.invokeCommand(element, payload)\n case 'form':\n return driver.invokeCommand(element, payload, event)\n case 'frame':\n return driver.invokeCommand(driver.frame, payload)\n case 'window':\n return driver.invokeCommand(payload)\n }\n } catch (error) {\n dispatch(commandEvents.clientError, element, {\n detail: { ...payload, error }\n })\n }\n}\n\nself.TurboBoost = self.TurboBoost || {}\n\nself.TurboBoost = {\n ...self.TurboBoost,\n\n stateEvents,\n\n get state() {\n return state.current\n },\n\n get stateDelta() {\n return state.delta\n }\n}\n\nif (!self.TurboBoost.Commands) {\n // wire things up and setup defaults for event delegation\n delegates.handler = invokeCommand\n delegates.register('click', [`[${schema.commandAttribute}]`])\n delegates.register('submit', [`form[${schema.commandAttribute}]`])\n delegates.register('change', [\n `input[${schema.commandAttribute}]`,\n `select[${schema.commandAttribute}]`,\n `textarea[${schema.commandAttribute}]`\n ])\n\n self.TurboBoost.Commands = {\n confirmation,\n logger,\n schema,\n events: commandEvents,\n registerEventDelegate: delegates.register,\n get eventDelegates() {\n return delegates.events\n }\n }\n}\n\nexport default self.TurboBoost.Commands\n"],
5
- "mappings": "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",
6
- "names": ["Meta", "value", "meta_default", "commandEvents", "stateEvents", "allEvents", "__spreadValues", "dispatch", "name", "target", "options", "resolve", "evt", "__spreadProps", "head", "observable", "object", "parent", "proxy", "target", "key", "dispatch", "stateEvents", "meta_default", "value", "receiver", "index", "observable_default", "loadedState", "currentState", "changedState", "loadStateTimeout", "loadState", "meta_default", "loadStateLater", "json", "observable_default", "__spreadValues", "dispatch", "stateEvents", "commandEvents", "event", "key", "value", "state_default", "replaceDocument", "content", "head", "tail", "headIndex", "tailIndex", "html", "append", "renderer_default", "active", "add", "payload", "remove", "id", "activity_default", "finish", "event", "dispatch", "commandEvents", "activity_default", "lifecycle_default", "frameSources", "event", "frame", "fetchOptions", "meta_default", "acceptHeaders", "entry", "state_default", "chunk", "i", "response", "error", "dispatch", "lifecycle_default", "__spreadProps", "__spreadValues", "content", "renderer_default", "schema", "schema_default", "__spreadValues", "confirmation", "message", "isTurboMethod", "event", "isTurboForm", "element", "frame", "target", "schema_default", "shouldDelegate", "commandEvents", "confirmation_default", "events", "eventListener", "register", "eventName", "selectors", "match", "evt", "__spreadValues", "getRegisteredEventForElement", "element", "selector", "el", "isRegisteredForElement", "delegates_default", "fn", "findClosestCommand", "element", "schema_default", "findClosestFrameWithSource", "assignElementValueToPayload", "payload", "memo", "option", "buildAttributePayload", "attr", "value", "elements_default", "invokeCommand", "form", "payload", "event", "meta_default", "input", "form_default", "build", "urlString", "payload", "a", "url", "urls_default", "invokeCommand", "frame", "payload", "src", "__spreadValues", "urls_default", "frame_default", "invokeCommand", "element", "payload", "src", "__spreadValues", "urls_default", "method_default", "aborted", "event", "xhr", "dispatch", "lifecycle_default", "__spreadProps", "__spreadValues", "errored", "renderer_default", "error", "loaded", "content", "invokeCommand", "payload", "src", "urls_default", "meta_default", "state_default", "chunk", "i", "ex", "message", "window_default", "src", "element", "frame", "find", "elements_default", "turboFrame", "turboMethod", "form_default", "method_default", "frame_default", "window_default", "drivers_default", "currentLevel", "logLevels", "allEvents", "name", "event", "target", "detail", "logger_default", "value", "v4", "c", "uuids_default", "buildCommandPayload", "id", "element", "schema_default", "elements_default", "invokeCommand", "event", "payload", "delegates_default", "commandId", "uuids_default", "driver", "drivers_default", "__spreadProps", "__spreadValues", "startEvent", "dispatch", "commandEvents", "activity_default", "meta_default", "error", "stateEvents", "state_default", "confirmation_default", "logger_default", "javascript_default"]
3
+ "sources": ["../../../javascript/events.js", "../../../javascript/state/observable.js", "../../../javascript/state/index.js", "../../../javascript/renderer.js", "../../../javascript/activity.js", "../../../javascript/lifecycle.js", "../../../javascript/turbo.js", "../../../javascript/schema.js", "../../../javascript/confirmation.js", "../../../javascript/delegates.js", "../../../javascript/elements.js", "../../../javascript/drivers/form.js", "../../../javascript/urls.js", "../../../javascript/drivers/frame.js", "../../../javascript/drivers/method.js", "../../../javascript/drivers/window.js", "../../../javascript/drivers/index.js", "../../../javascript/logger.js", "../../../javascript/uuids.js", "../../../javascript/version.js", "../../../javascript/index.js"],
4
+ "sourcesContent": ["export const commandEvents = {\n start: 'turbo-boost:command:start',\n success: 'turbo-boost:command:success',\n finish: 'turbo-boost:command:finish',\n abort: 'turbo-boost:command:abort',\n clientError: 'turbo-boost:command:client-error',\n serverError: 'turbo-boost:command:server-error'\n}\n\nexport const stateEvents = {\n stateLoad: 'turbo-boost:state:load',\n stateChange: 'turbo-boost:state:change'\n}\n\nexport const allEvents = { ...commandEvents, ...stateEvents }\n\nexport function dispatch(name, target, options = {}) {\n return new Promise(resolve => {\n options = options || {}\n options.detail = options.detail || {}\n target = target || document\n const evt = new CustomEvent(name, { ...options, bubbles: true })\n target.dispatchEvent(evt)\n resolve(evt)\n })\n}\n", "import { dispatch, stateEvents as events } from '../events'\n\nlet head\n\nfunction observable(object, parent = null) {\n if (!object || typeof object !== 'object') return object\n\n const proxy = new Proxy(object, {\n deleteProperty(target, key) {\n delete target[key]\n dispatch(events.stateChange, document, { detail: { state: head } })\n return true\n },\n\n set(target, key, value, receiver) {\n target[key] = observable(value, this)\n dispatch(events.stateChange, document, { detail: { state: head } })\n return true\n }\n })\n\n if (Array.isArray(object)) {\n object.forEach((value, index) => (object[index] = observable(value, proxy)))\n } else if (typeof object === 'object') {\n for (const [key, value] of Object.entries(object)) object[key] = observable(value, proxy)\n }\n\n if (!parent) head = proxy\n return proxy\n}\n\nexport default observable\n", "// TODO: Consider moving State to its own library\nimport observable from './observable'\nimport { dispatch, commandEvents, stateEvents } from '../events'\n\nlet initialState, currentState, changedState, signedState\n\nfunction initialize(initial, signed) {\n const json = JSON.parse(initial)\n initialState = { ...json }\n signedState = signed\n currentState = observable(json)\n changedState = {}\n setTimeout(() =>\n dispatch(stateEvents.stateLoad, document, {\n detail: { state: currentState }\n })\n )\n}\n\naddEventListener(stateEvents.stateChange, event => {\n for (const [key, value] of Object.entries(currentState))\n if (initialState[key] !== value) changedState[key] = value\n})\n\nexport default {\n initialize,\n events: stateEvents,\n\n get initial() {\n return initialState\n },\n\n get current() {\n return currentState\n },\n\n get changed() {\n return changedState\n },\n\n get signed() {\n return signedState\n }\n}\n", "function replaceDocument(content) {\n const head = '<html'\n const tail = '</html'\n const headIndex = content.indexOf(head)\n const tailIndex = content.lastIndexOf(tail)\n if (headIndex >= 0 && tailIndex >= 0) {\n const html = content.slice(content.indexOf('>', headIndex) + 1, tailIndex)\n document.documentElement.innerHTML = html\n }\n}\n\nfunction append(content) {\n document.body.insertAdjacentHTML('beforeend', content)\n}\n\nexport default { append, replaceDocument }\n", "const active = {}\n\nfunction add(payload) {\n active[payload.id] = payload\n}\n\nfunction remove(id) {\n delete active[id]\n}\n\nexport default {\n add,\n remove,\n get commands() {\n return [...Object.values(active)]\n },\n get length() {\n return Object.keys(active).length\n }\n}\n", "import activity from './activity'\nimport { dispatch, commandEvents } from './events'\n\nfunction finish(event) {\n event.detail.endedAt = Date.now()\n event.detail.milliseconds = event.detail.endedAt - event.detail.startedAt\n setTimeout(() => dispatch(commandEvents.finish, event.target, { detail: event.detail }), 25)\n}\n\n// TODO: forward source event to finish (error or success)\naddEventListener(commandEvents.serverError, finish)\naddEventListener(commandEvents.success, finish)\naddEventListener(commandEvents.finish, event => activity.remove(event.detail.id), true)\n\nexport default { events: commandEvents }\n", "import state from './state'\nimport renderer from './renderer'\nimport { dispatch } from './events'\nimport lifecycle from './lifecycle'\n\nconst frameSources = {}\n\n// fires before making a turbo HTTP request\naddEventListener('turbo:before-fetch-request', event => {\n const frame = event.target.closest('turbo-frame')\n const { fetchOptions } = event.detail\n\n // command invoked and busy\n if (self.TurboBoost?.Commands?.busy) {\n let acceptHeaders = ['text/vnd.turbo-boost.html', fetchOptions.headers['Accept']]\n acceptHeaders = acceptHeaders.filter(entry => entry && entry.trim().length > 0).join(', ')\n fetchOptions.headers['Accept'] = acceptHeaders\n }\n})\n\n// fires after receiving a turbo HTTP response\naddEventListener('turbo:before-fetch-response', event => {\n const frame = event.target.closest('turbo-frame')\n const { fetchResponse: response } = event.detail\n\n if (frame) frameSources[frame.id] = frame.src\n\n if (response.header('TurboBoost')) {\n if (response.statusCode < 200 || response.statusCode > 399) {\n const error = `Server returned a ${response.statusCode} status code! TurboBoost Commands require 2XX-3XX status codes.`\n dispatch(lifecycle.events.clientError, document, { detail: { ...event.detail, error } }, true)\n }\n\n if (response.header('TurboBoost') === 'Append') {\n event.preventDefault()\n response.responseText.then(content => renderer.append(content))\n }\n }\n})\n\n// fires when a frame element is navigated and finishes loading\naddEventListener('turbo:frame-load', event => {\n const frame = event.target.closest('turbo-frame')\n frame.dataset.turboBoostSrc = frameSources[frame.id] || frame.src || frame.dataset.turboBoostSrc\n delete frameSources[frame.id]\n})\n", "const schema = {\n // attributes\n frameAttribute: 'data-turbo-frame',\n methodAttribute: 'data-turbo-method',\n commandAttribute: 'data-turbo-command',\n confirmAttribute: 'data-turbo-confirm'\n}\n\nexport default { ...schema }\n", "import { commandEvents } from './events'\nimport schema from './schema'\n\nconst confirmation = {\n method: message => Promise.resolve(confirm(message))\n}\n\nconst isTurboMethod = event => event.detail.driver === 'method'\n\nconst isTurboForm = event => {\n if (event.detail.driver !== 'form') return false\n\n const element = event.target\n const frame = element.closest('turbo-frame')\n const target = element.closest(`[${schema.frameAttribute}]`)\n return !!(frame || target)\n}\n\nconst shouldDelegate = event => isTurboMethod(event) || isTurboForm(event)\n\ndocument.addEventListener(commandEvents.start, async event => {\n const message = event.target.getAttribute(schema.confirmAttribute)\n if (!message) return\n\n event.detail.confirmation = true\n\n if (shouldDelegate(event)) return // delegate confirmation handling to Turbo\n\n const proceed = await confirmation.method(message)\n if (!proceed) event.preventDefault()\n})\n\nexport default confirmation\n", "let events = []\nlet eventListener\n\nfunction register(eventName, selectors) {\n const match = events.find(evt => evt.name === eventName)\n if (match) events.splice(events.indexOf(match), 1)\n events = [{ name: eventName, selectors }, ...events]\n\n document.removeEventListener(eventName, eventListener, true)\n document.addEventListener(eventName, eventListener, true)\n\n return { ...events.find(evt => evt.name === eventName) }\n}\n\nfunction getRegisteredEventForElement(element) {\n return events.find(evt =>\n evt.selectors.find(selector => Array.from(document.querySelectorAll(selector)).find(el => el === element))\n )\n}\n\nfunction isRegisteredForElement(eventName, element) {\n const evt = getRegisteredEventForElement(element)\n return evt && evt.name === eventName\n}\n\nexport default {\n register,\n isRegisteredForElement,\n get events() {\n return [...events]\n },\n set handler(fn) {\n eventListener = fn\n }\n}\n", "import schema from './schema'\nimport lifecycle from './lifecycle'\n\nfunction findClosestCommand(element) {\n return element.closest(`[${schema.commandAttribute}]`)\n}\n\nfunction findClosestFrameWithSource(element) {\n return (\n element.closest('turbo-frame[src]') ||\n element.closest('turbo-frame[data-turbo-frame-src]') ||\n element.closest('turbo-frame')\n )\n}\n\nfunction assignElementValueToPayload(element, payload = {}) {\n if (element.tagName.toLowerCase() !== 'select') return (payload.value = element.value || null)\n\n if (!element.multiple) return (payload.value = element.options[element.selectedIndex].value)\n\n payload.values = Array.from(element.options).reduce((memo, option) => {\n if (option.selected) memo.push(option.value)\n return memo\n }, [])\n}\n\nfunction buildAttributePayload(element) {\n const payload = Array.from(element.attributes).reduce((memo, attr) => {\n let value = attr.value\n memo[attr.name] = value\n return memo\n }, {})\n\n payload.tag = element.tagName\n payload.checked = !!element.checked\n payload.disabled = !!element.disabled\n assignElementValueToPayload(element, payload)\n\n // reduce payload size to keep URL length smaller\n delete payload.class\n delete payload.action\n delete payload.href\n delete payload[schema.commandAttribute]\n delete payload[schema.frameAttribute]\n\n return payload\n}\n\nexport default {\n buildAttributePayload,\n findClosestCommand,\n findClosestFrameWithSource\n}\n", "function invokeCommand(form, payload = {}, event = {}) {\n const input = form.querySelector('input[name=\"turbo_boost_command\"]') || document.createElement('input')\n input.type = 'hidden'\n input.name = 'turbo_boost_command'\n input.value = JSON.stringify(payload)\n form.appendChild(input)\n}\n\nexport default { invokeCommand }\n", "function build(urlString, payload = {}) {\n const a = document.createElement('a')\n a.href = urlString\n const url = new URL(a)\n url.searchParams.set('tbc', JSON.stringify(payload))\n return url\n}\n\nexport default { build }\n", "import urls from '../urls'\n\nfunction invokeCommand(frame, payload) {\n const src = payload.src\n payload = { ...payload }\n delete payload.src\n frame.src = urls.build(src, payload)\n}\n\nexport default { invokeCommand }\n", "import urls from '../urls'\n\nfunction invokeCommand(element, payload = {}) {\n const src = payload.src\n payload = { ...payload }\n delete payload.src\n delete payload.href\n element.setAttribute('href', urls.build(src, payload))\n}\n\nexport default { invokeCommand }\n", "import state from '../state'\nimport { dispatch } from '../events'\nimport lifecycle from '../lifecycle'\nimport urls from '../urls'\nimport renderer from '../renderer'\n\nfunction aborted(event) {\n const xhr = event.target\n dispatch(lifecycle.events.abort, document, {\n detail: { ...event.detail, xhr }\n })\n}\n\nfunction errored(event) {\n const xhr = event.target\n\n const append =\n xhr.getResponseHeader('TurboBoost') === 'Append' ||\n xhr.getResponseHeader('Content-Type').startsWith('text/vnd.turbo-boost.html')\n\n if (append) renderer.append(xhr.responseText)\n\n const error = `Server returned a ${xhr.status} status code! TurboBoost Commands require 2XX-3XX status codes.`\n\n dispatch(lifecycle.events.clientError, document, { detail: { ...event.detail, error, xhr } }, true)\n}\n\nfunction loaded(event) {\n const xhr = event.target\n if (xhr.status < 200 || xhr.status > 399) return errored(event)\n const content = xhr.responseText\n const append =\n xhr.getResponseHeader('TurboBoost') === 'Append' ||\n xhr.getResponseHeader('Content-Type').startsWith('text/vnd.turbo-boost.html')\n append ? renderer.append(xhr.responseText) : renderer.replaceDocument(xhr.responseText)\n}\n\nfunction invokeCommand(payload) {\n const src = payload.src\n payload = { ...payload }\n delete payload.src\n\n try {\n const xhr = new XMLHttpRequest()\n xhr.open('GET', urls.build(src, payload), true)\n xhr.setRequestHeader('Accept', 'text/vnd.turbo-boost.html, text/html, application/xhtml+xml')\n xhr.addEventListener('abort', aborted)\n xhr.addEventListener('error', errored)\n xhr.addEventListener('load', loaded)\n xhr.send()\n } catch (ex) {\n const message = `Unexpected error sending HTTP request! ${ex.message}`\n errored(ex, { detail: { message } })\n }\n}\n\nexport default { invokeCommand }\n", "import elements from '../elements'\nimport formDriver from './form'\nimport frameDriver from './frame'\nimport methodDriver from './method'\nimport windowDriver from './window'\n\nfunction src(element, frame) {\n frame = frame || { dataset: {} }\n return element.href || frame.src || frame.dataset.turboBoostSrc || location.href\n}\n\nfunction find(element) {\n let frame = elements.findClosestFrameWithSource(element)\n\n const { turboFrame, turboMethod } = element.dataset\n\n if (element.tagName.toLowerCase() === 'form')\n return {\n name: 'form',\n reason: 'Element is a form.',\n frame,\n src: element.action,\n invokeCommand: formDriver.invokeCommand\n }\n\n if (turboMethod && turboMethod.length > 0)\n return {\n name: 'method',\n reason: 'Element defines data-turbo-method.',\n frame,\n src: element.href,\n invokeCommand: methodDriver.invokeCommand\n }\n\n // element targets a frame that is not _self\n if (turboFrame && turboFrame !== '_self') {\n frame = document.getElementById(turboFrame)\n return {\n name: 'frame',\n reason: 'element targets a frame that is not _self',\n frame,\n src: src(element, frame),\n invokeCommand: frameDriver.invokeCommand\n }\n }\n\n // element does NOT target a frame or targets _self and is contained by a frame\n if ((!turboFrame || turboFrame === '_self') && frame)\n return {\n name: 'frame',\n reason: 'element does NOT target a frame or targets _self and is contained by a frame',\n frame,\n src: src(element, frame),\n invokeCommand: frameDriver.invokeCommand\n }\n\n // element matches one or more of the following conditions\n // - targets _top\n // - does NOT target a frame\n // - is NOT contained by a frame\n return {\n name: 'window',\n reason:\n 'element matches one or more of the following conditions (targets _top, does NOT target a frame, is NOT contained by a frame)',\n frame: null,\n src: src(element),\n invokeCommand: windowDriver.invokeCommand\n }\n}\n\nexport default { find }\n", "import { allEvents as events } from './events'\n\nlet currentLevel = 'unknown'\n\nconst logLevels = {\n debug: Object.values(events),\n info: Object.values(events),\n warn: [events.abort, events.clientError, events.serverError],\n error: [events.clientError, events.serverError],\n unknown: []\n}\n\nObject.values(events).forEach(name => {\n addEventListener(name, event => {\n if (logLevels[currentLevel].includes(event.type)) {\n const { target, detail } = event\n console[currentLevel](event.type, { target, detail })\n }\n })\n})\n\nexport default {\n get level() {\n return currentLevel\n },\n set level(value) {\n if (!Object.keys(logLevels).includes(value)) value = 'unknown'\n return (currentLevel = value)\n }\n}\n", "function v4() {\n return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, c =>\n (c ^ (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (c / 4)))).toString(16)\n )\n}\n\nexport default { v4 }\n", "export default '0.1.1'\n", "import './turbo'\nimport schema from './schema'\nimport { dispatch, commandEvents } from './events'\nimport activity from './activity'\nimport confirmation from './confirmation'\nimport delegates from './delegates'\nimport drivers from './drivers'\nimport elements from './elements'\nimport lifecycle from './lifecycle'\nimport logger from './logger'\nimport state from './state'\nimport urls from './urls'\nimport uuids from './uuids'\nimport VERSION from './version'\n\nconst TurboBoost = self.TurboBoost || {}\n\nconst Commands = {\n VERSION,\n busy: false,\n confirmation,\n logger,\n schema,\n events: commandEvents,\n registerEventDelegate: delegates.register,\n get eventDelegates() {\n return delegates.events\n }\n}\n\nfunction buildCommandPayload(id, element) {\n return {\n id, // uniquely identifies the command\n name: element.getAttribute(schema.commandAttribute),\n elementId: element.id.length > 0 ? element.id : null,\n elementAttributes: elements.buildAttributePayload(element),\n startedAt: Date.now(),\n token: Commands.token, // command token (used for CSRF protection)\n signedState: state.signed, // server side state\n clientState: state.changed // client side state (delta of optimistic updates)\n }\n}\n\nasync function invokeCommand(event) {\n let element\n let payload = {}\n\n try {\n element = elements.findClosestCommand(event.target)\n if (!element) return\n if (!delegates.isRegisteredForElement(event.type, element)) return\n\n const commandId = `turbo-command-${uuids.v4()}`\n let driver = drivers.find(element)\n let payload = {\n ...buildCommandPayload(commandId, element),\n driver: driver.name,\n frameId: driver.frame ? driver.frame.id : null,\n src: driver.src\n }\n\n const startEvent = await dispatch(commandEvents.start, element, {\n cancelable: true,\n detail: payload\n })\n\n if (startEvent.defaultPrevented || (startEvent.detail.confirmation && event.defaultPrevented))\n return dispatch(commandEvents.abort, element, {\n detail: {\n message: `An event handler for '${commandEvents.start}' prevented default behavior and blocked command invocation!`,\n source: startEvent\n }\n })\n\n // the element and thus the driver may have changed based on the start event handler(s)\n driver = drivers.find(element)\n payload = {\n ...buildCommandPayload(commandId, element),\n driver: driver.name,\n frameId: driver.frame ? driver.frame.id : null,\n src: driver.src\n }\n\n activity.add(payload)\n\n if (['frame', 'window'].includes(driver.name)) event.preventDefault()\n\n Commands.busy = true\n setTimeout(() => (Commands.busy = false), 10)\n\n switch (driver.name) {\n case 'method':\n return driver.invokeCommand(element, payload)\n case 'form':\n return driver.invokeCommand(element, payload, event)\n case 'frame':\n return driver.invokeCommand(driver.frame, payload)\n case 'window':\n return driver.invokeCommand(payload)\n }\n } catch (error) {\n dispatch(commandEvents.clientError, element, {\n detail: { ...payload, error }\n })\n }\n}\n\nself.TurboBoost = { ...TurboBoost }\n\nif (!self.TurboBoost.Commands) {\n // wire things up and setup defaults for event delegation\n delegates.handler = invokeCommand\n delegates.register('click', [`[${schema.commandAttribute}]`])\n delegates.register('submit', [`form[${schema.commandAttribute}]`])\n delegates.register('change', [\n `input[${schema.commandAttribute}]`,\n `select[${schema.commandAttribute}]`,\n `textarea[${schema.commandAttribute}]`\n ])\n\n self.TurboBoost.Commands = Commands\n self.TurboBoost.State = state\n}\n\nexport default Commands\n"],
5
+ "mappings": "ibAAO,IAAMA,EAAgB,CAC3B,MAAO,4BACP,QAAS,8BACT,OAAQ,6BACR,MAAO,4BACP,YAAa,mCACb,YAAa,kCACf,EAEaC,EAAc,CACzB,UAAW,yBACX,YAAa,0BACf,EAEaC,EAAYC,IAAA,GAAKH,GAAkBC,GAEzC,SAASG,EAASC,EAAMC,EAAQC,EAAU,CAAC,EAAG,CACnD,OAAO,IAAI,QAAQC,GAAW,CAC5BD,EAAUA,GAAW,CAAC,EACtBA,EAAQ,OAASA,EAAQ,QAAU,CAAC,EACpCD,EAASA,GAAU,SACnB,IAAMG,EAAM,IAAI,YAAYJ,EAAMK,EAAAP,EAAA,GAAKI,GAAL,CAAc,QAAS,EAAK,EAAC,EAC/DD,EAAO,cAAcG,CAAG,EACxBD,EAAQC,CAAG,CACb,CAAC,CACH,CCvBA,IAAIE,EAEJ,SAASC,EAAWC,EAAQC,EAAS,KAAM,CACzC,GAAI,CAACD,GAAU,OAAOA,GAAW,SAAU,OAAOA,EAElD,IAAME,EAAQ,IAAI,MAAMF,EAAQ,CAC9B,eAAeG,EAAQC,EAAK,CAC1B,cAAOD,EAAOC,CAAG,EACjBC,EAASC,EAAO,YAAa,SAAU,CAAE,OAAQ,CAAE,MAAOR,CAAK,CAAE,CAAC,EAC3D,EACT,EAEA,IAAIK,EAAQC,EAAKG,EAAOC,EAAU,CAChC,OAAAL,EAAOC,CAAG,EAAIL,EAAWQ,EAAO,IAAI,EACpCF,EAASC,EAAO,YAAa,SAAU,CAAE,OAAQ,CAAE,MAAOR,CAAK,CAAE,CAAC,EAC3D,EACT,CACF,CAAC,EAED,GAAI,MAAM,QAAQE,CAAM,EACtBA,EAAO,QAAQ,CAACO,EAAOE,IAAWT,EAAOS,CAAK,EAAIV,EAAWQ,EAAOL,CAAK,CAAE,UAClE,OAAOF,GAAW,SAC3B,OAAW,CAACI,EAAKG,CAAK,IAAK,OAAO,QAAQP,CAAM,EAAGA,EAAOI,CAAG,EAAIL,EAAWQ,EAAOL,CAAK,EAG1F,OAAKD,IAAQH,EAAOI,GACbA,CACT,CAEA,IAAOQ,EAAQX,EC3Bf,IAAIY,EAAcC,EAAcC,EAAcC,EAE9C,SAASC,GAAWC,EAASC,EAAQ,CACnC,IAAMC,EAAO,KAAK,MAAMF,CAAO,EAC/BL,EAAeQ,EAAA,GAAKD,GACpBJ,EAAcG,EACdL,EAAeQ,EAAWF,CAAI,EAC9BL,EAAe,CAAC,EAChB,WAAW,IACTQ,EAASC,EAAY,UAAW,SAAU,CACxC,OAAQ,CAAE,MAAOV,CAAa,CAChC,CAAC,CACH,CACF,CAEA,iBAAiBU,EAAY,YAAaC,GAAS,CACjD,OAAW,CAACC,EAAKC,CAAK,IAAK,OAAO,QAAQb,CAAY,EAChDD,EAAaa,CAAG,IAAMC,IAAOZ,EAAaW,CAAG,EAAIC,EACzD,CAAC,EAED,IAAOC,EAAQ,CACb,WAAAX,GACA,OAAQO,EAER,IAAI,SAAU,CACZ,OAAOX,CACT,EAEA,IAAI,SAAU,CACZ,OAAOC,CACT,EAEA,IAAI,SAAU,CACZ,OAAOC,CACT,EAEA,IAAI,QAAS,CACX,OAAOC,CACT,CACF,EC3CA,SAASa,GAAgBC,EAAS,CAChC,IAAMC,EAAO,QACPC,EAAO,SACPC,EAAYH,EAAQ,QAAQC,CAAI,EAChCG,EAAYJ,EAAQ,YAAYE,CAAI,EAC1C,GAAIC,GAAa,GAAKC,GAAa,EAAG,CACpC,IAAMC,EAAOL,EAAQ,MAAMA,EAAQ,QAAQ,IAAKG,CAAS,EAAI,EAAGC,CAAS,EACzE,SAAS,gBAAgB,UAAYC,CACvC,CACF,CAEA,SAASC,GAAON,EAAS,CACvB,SAAS,KAAK,mBAAmB,YAAaA,CAAO,CACvD,CAEA,IAAOO,EAAQ,CAAE,OAAAD,GAAQ,gBAAAP,EAAgB,ECfzC,IAAMS,EAAS,CAAC,EAEhB,SAASC,GAAIC,EAAS,CACpBF,EAAOE,EAAQ,EAAE,EAAIA,CACvB,CAEA,SAASC,GAAOC,EAAI,CAClB,OAAOJ,EAAOI,CAAE,CAClB,CAEA,IAAOC,EAAQ,CACb,IAAAJ,GACA,OAAAE,GACA,IAAI,UAAW,CACb,MAAO,CAAC,GAAG,OAAO,OAAOH,CAAM,CAAC,CAClC,EACA,IAAI,QAAS,CACX,OAAO,OAAO,KAAKA,CAAM,EAAE,MAC7B,CACF,EChBA,SAASM,EAAOC,EAAO,CACrBA,EAAM,OAAO,QAAU,KAAK,IAAI,EAChCA,EAAM,OAAO,aAAeA,EAAM,OAAO,QAAUA,EAAM,OAAO,UAChE,WAAW,IAAMC,EAASC,EAAc,OAAQF,EAAM,OAAQ,CAAE,OAAQA,EAAM,MAAO,CAAC,EAAG,EAAE,CAC7F,CAGA,iBAAiBE,EAAc,YAAaH,CAAM,EAClD,iBAAiBG,EAAc,QAASH,CAAM,EAC9C,iBAAiBG,EAAc,OAAQF,GAASG,EAAS,OAAOH,EAAM,OAAO,EAAE,EAAG,EAAI,EAEtF,IAAOI,EAAQ,CAAE,OAAQF,CAAc,ECTvC,IAAMG,EAAe,CAAC,EAGtB,iBAAiB,6BAA8BC,GAAS,CARxD,IAAAC,EAAAC,EASE,IAAMC,EAAQH,EAAM,OAAO,QAAQ,aAAa,EAC1C,CAAE,aAAAI,CAAa,EAAIJ,EAAM,OAG/B,IAAIE,GAAAD,EAAA,KAAK,aAAL,YAAAA,EAAiB,WAAjB,MAAAC,EAA2B,KAAM,CACnC,IAAIG,EAAgB,CAAC,4BAA6BD,EAAa,QAAQ,MAAS,EAChFC,EAAgBA,EAAc,OAAOC,GAASA,GAASA,EAAM,KAAK,EAAE,OAAS,CAAC,EAAE,KAAK,IAAI,EACzFF,EAAa,QAAQ,OAAYC,CACnC,CACF,CAAC,EAGD,iBAAiB,8BAA+BL,GAAS,CACvD,IAAMG,EAAQH,EAAM,OAAO,QAAQ,aAAa,EAC1C,CAAE,cAAeO,CAAS,EAAIP,EAAM,OAI1C,GAFIG,IAAOJ,EAAaI,EAAM,EAAE,EAAIA,EAAM,KAEtCI,EAAS,OAAO,YAAY,EAAG,CACjC,GAAIA,EAAS,WAAa,KAAOA,EAAS,WAAa,IAAK,CAC1D,IAAMC,EAAQ,qBAAqBD,EAAS,UAAU,kEACtDE,EAASC,EAAU,OAAO,YAAa,SAAU,CAAE,OAAQC,EAAAC,EAAA,GAAKZ,EAAM,QAAX,CAAmB,MAAAQ,CAAM,EAAE,EAAG,EAAI,CAC/F,CAEID,EAAS,OAAO,YAAY,IAAM,WACpCP,EAAM,eAAe,EACrBO,EAAS,aAAa,KAAKM,GAAWC,EAAS,OAAOD,CAAO,CAAC,EAElE,CACF,CAAC,EAGD,iBAAiB,mBAAoBb,GAAS,CAC5C,IAAMG,EAAQH,EAAM,OAAO,QAAQ,aAAa,EAChDG,EAAM,QAAQ,cAAgBJ,EAAaI,EAAM,EAAE,GAAKA,EAAM,KAAOA,EAAM,QAAQ,cACnF,OAAOJ,EAAaI,EAAM,EAAE,CAC9B,CAAC,EC7CD,IAAMY,GAAS,CAEb,eAAgB,mBAChB,gBAAiB,oBACjB,iBAAkB,qBAClB,iBAAkB,oBACpB,EAEOC,EAAQC,EAAA,GAAKF,ICLpB,IAAMG,EAAe,CACnB,OAAQC,GAAW,QAAQ,QAAQ,QAAQA,CAAO,CAAC,CACrD,EAEMC,GAAgBC,GAASA,EAAM,OAAO,SAAW,SAEjDC,GAAcD,GAAS,CAC3B,GAAIA,EAAM,OAAO,SAAW,OAAQ,MAAO,GAE3C,IAAME,EAAUF,EAAM,OAChBG,EAAQD,EAAQ,QAAQ,aAAa,EACrCE,EAASF,EAAQ,QAAQ,IAAIG,EAAO,cAAc,GAAG,EAC3D,MAAO,CAAC,EAAEF,GAASC,EACrB,EAEME,GAAiBN,GAASD,GAAcC,CAAK,GAAKC,GAAYD,CAAK,EAEzE,SAAS,iBAAiBO,EAAc,MAAO,MAAMP,GAAS,CAC5D,IAAMF,EAAUE,EAAM,OAAO,aAAaK,EAAO,gBAAgB,EAKjE,GAJI,CAACP,IAELE,EAAM,OAAO,aAAe,GAExBM,GAAeN,CAAK,GAAG,OAEX,MAAMH,EAAa,OAAOC,CAAO,GACnCE,EAAM,eAAe,CACrC,CAAC,EAED,IAAOQ,EAAQX,EChCf,IAAIY,EAAS,CAAC,EACVC,EAEJ,SAASC,GAASC,EAAWC,EAAW,CACtC,IAAMC,EAAQL,EAAO,KAAKM,GAAOA,EAAI,OAASH,CAAS,EACvD,OAAIE,GAAOL,EAAO,OAAOA,EAAO,QAAQK,CAAK,EAAG,CAAC,EACjDL,EAAS,CAAC,CAAE,KAAMG,EAAW,UAAAC,CAAU,EAAG,GAAGJ,CAAM,EAEnD,SAAS,oBAAoBG,EAAWF,EAAe,EAAI,EAC3D,SAAS,iBAAiBE,EAAWF,EAAe,EAAI,EAEjDM,EAAA,GAAKP,EAAO,KAAKM,GAAOA,EAAI,OAASH,CAAS,EACvD,CAEA,SAASK,GAA6BC,EAAS,CAC7C,OAAOT,EAAO,KAAKM,GACjBA,EAAI,UAAU,KAAKI,GAAY,MAAM,KAAK,SAAS,iBAAiBA,CAAQ,CAAC,EAAE,KAAKC,GAAMA,IAAOF,CAAO,CAAC,CAC3G,CACF,CAEA,SAASG,GAAuBT,EAAWM,EAAS,CAClD,IAAMH,EAAME,GAA6BC,CAAO,EAChD,OAAOH,GAAOA,EAAI,OAASH,CAC7B,CAEA,IAAOU,EAAQ,CACb,SAAAX,GACA,uBAAAU,GACA,IAAI,QAAS,CACX,MAAO,CAAC,GAAGZ,CAAM,CACnB,EACA,IAAI,QAAQc,EAAI,CACdb,EAAgBa,CAClB,CACF,EC/BA,SAASC,GAAmBC,EAAS,CACnC,OAAOA,EAAQ,QAAQ,IAAIC,EAAO,gBAAgB,GAAG,CACvD,CAEA,SAASC,GAA2BF,EAAS,CAC3C,OACEA,EAAQ,QAAQ,kBAAkB,GAClCA,EAAQ,QAAQ,mCAAmC,GACnDA,EAAQ,QAAQ,aAAa,CAEjC,CAEA,SAASG,GAA4BH,EAASI,EAAU,CAAC,EAAG,CAC1D,GAAIJ,EAAQ,QAAQ,YAAY,IAAM,SAAU,OAAQI,EAAQ,MAAQJ,EAAQ,OAAS,KAEzF,GAAI,CAACA,EAAQ,SAAU,OAAQI,EAAQ,MAAQJ,EAAQ,QAAQA,EAAQ,aAAa,EAAE,MAEtFI,EAAQ,OAAS,MAAM,KAAKJ,EAAQ,OAAO,EAAE,OAAO,CAACK,EAAMC,KACrDA,EAAO,UAAUD,EAAK,KAAKC,EAAO,KAAK,EACpCD,GACN,CAAC,CAAC,CACP,CAEA,SAASE,GAAsBP,EAAS,CACtC,IAAMI,EAAU,MAAM,KAAKJ,EAAQ,UAAU,EAAE,OAAO,CAACK,EAAMG,IAAS,CACpE,IAAIC,EAAQD,EAAK,MACjB,OAAAH,EAAKG,EAAK,IAAI,EAAIC,EACXJ,CACT,EAAG,CAAC,CAAC,EAEL,OAAAD,EAAQ,IAAMJ,EAAQ,QACtBI,EAAQ,QAAU,CAAC,CAACJ,EAAQ,QAC5BI,EAAQ,SAAW,CAAC,CAACJ,EAAQ,SAC7BG,GAA4BH,EAASI,CAAO,EAG5C,OAAOA,EAAQ,MACf,OAAOA,EAAQ,OACf,OAAOA,EAAQ,KACf,OAAOA,EAAQH,EAAO,gBAAgB,EACtC,OAAOG,EAAQH,EAAO,cAAc,EAE7BG,CACT,CAEA,IAAOM,EAAQ,CACb,sBAAAH,GACA,mBAAAR,GACA,2BAAAG,EACF,ECpDA,SAASS,GAAcC,EAAMC,EAAU,CAAC,EAAGC,EAAQ,CAAC,EAAG,CACrD,IAAMC,EAAQH,EAAK,cAAc,mCAAmC,GAAK,SAAS,cAAc,OAAO,EACvGG,EAAM,KAAO,SACbA,EAAM,KAAO,sBACbA,EAAM,MAAQ,KAAK,UAAUF,CAAO,EACpCD,EAAK,YAAYG,CAAK,CACxB,CAEA,IAAOC,EAAQ,CAAE,cAAAL,EAAc,ECR/B,SAASM,GAAMC,EAAWC,EAAU,CAAC,EAAG,CACtC,IAAMC,EAAI,SAAS,cAAc,GAAG,EACpCA,EAAE,KAAOF,EACT,IAAMG,EAAM,IAAI,IAAID,CAAC,EACrB,OAAAC,EAAI,aAAa,IAAI,MAAO,KAAK,UAAUF,CAAO,CAAC,EAC5CE,CACT,CAEA,IAAOC,EAAQ,CAAE,MAAAL,EAAM,ECNvB,SAASM,GAAcC,EAAOC,EAAS,CACrC,IAAMC,EAAMD,EAAQ,IACpBA,EAAUE,EAAA,GAAKF,GACf,OAAOA,EAAQ,IACfD,EAAM,IAAMI,EAAK,MAAMF,EAAKD,CAAO,CACrC,CAEA,IAAOI,EAAQ,CAAE,cAAAN,EAAc,ECP/B,SAASO,GAAcC,EAASC,EAAU,CAAC,EAAG,CAC5C,IAAMC,EAAMD,EAAQ,IACpBA,EAAUE,EAAA,GAAKF,GACf,OAAOA,EAAQ,IACf,OAAOA,EAAQ,KACfD,EAAQ,aAAa,OAAQI,EAAK,MAAMF,EAAKD,CAAO,CAAC,CACvD,CAEA,IAAOI,EAAQ,CAAE,cAAAN,EAAc,ECJ/B,SAASO,GAAQC,EAAO,CACtB,IAAMC,EAAMD,EAAM,OAClBE,EAASC,EAAU,OAAO,MAAO,SAAU,CACzC,OAAQC,EAAAC,EAAA,GAAKL,EAAM,QAAX,CAAmB,IAAAC,CAAI,EACjC,CAAC,CACH,CAEA,SAASK,EAAQN,EAAO,CACtB,IAAMC,EAAMD,EAAM,QAGhBC,EAAI,kBAAkB,YAAY,IAAM,UACxCA,EAAI,kBAAkB,cAAc,EAAE,WAAW,2BAA2B,IAElEM,EAAS,OAAON,EAAI,YAAY,EAE5C,IAAMO,EAAQ,qBAAqBP,EAAI,MAAM,kEAE7CC,EAASC,EAAU,OAAO,YAAa,SAAU,CAAE,OAAQC,EAAAC,EAAA,GAAKL,EAAM,QAAX,CAAmB,MAAAQ,EAAO,IAAAP,CAAI,EAAE,EAAG,EAAI,CACpG,CAEA,SAASQ,GAAOT,EAAO,CACrB,IAAMC,EAAMD,EAAM,OAClB,GAAIC,EAAI,OAAS,KAAOA,EAAI,OAAS,IAAK,OAAOK,EAAQN,CAAK,EAC9D,IAAMU,EAAUT,EAAI,aAElBA,EAAI,kBAAkB,YAAY,IAAM,UACxCA,EAAI,kBAAkB,cAAc,EAAE,WAAW,2BAA2B,EACrEM,EAAS,OAAON,EAAI,YAAY,EAAIM,EAAS,gBAAgBN,EAAI,YAAY,CACxF,CAEA,SAASU,GAAcC,EAAS,CAC9B,IAAMC,EAAMD,EAAQ,IACpBA,EAAUP,EAAA,GAAKO,GACf,OAAOA,EAAQ,IAEf,GAAI,CACF,IAAMX,EAAM,IAAI,eAChBA,EAAI,KAAK,MAAOa,EAAK,MAAMD,EAAKD,CAAO,EAAG,EAAI,EAC9CX,EAAI,iBAAiB,SAAU,6DAA6D,EAC5FA,EAAI,iBAAiB,QAASF,EAAO,EACrCE,EAAI,iBAAiB,QAASK,CAAO,EACrCL,EAAI,iBAAiB,OAAQQ,EAAM,EACnCR,EAAI,KAAK,CACX,OAASc,EAAI,CACX,IAAMC,EAAU,0CAA0CD,EAAG,OAAO,GACpET,EAAQS,EAAI,CAAE,OAAQ,CAAE,QAAAC,CAAQ,CAAE,CAAC,CACrC,CACF,CAEA,IAAOC,EAAQ,CAAE,cAAAN,EAAc,EClD/B,SAASO,EAAIC,EAASC,EAAO,CAC3B,OAAAA,EAAQA,GAAS,CAAE,QAAS,CAAC,CAAE,EACxBD,EAAQ,MAAQC,EAAM,KAAOA,EAAM,QAAQ,eAAiB,SAAS,IAC9E,CAEA,SAASC,GAAKF,EAAS,CACrB,IAAIC,EAAQE,EAAS,2BAA2BH,CAAO,EAEjD,CAAE,WAAAI,EAAY,YAAAC,CAAY,EAAIL,EAAQ,QAE5C,OAAIA,EAAQ,QAAQ,YAAY,IAAM,OAC7B,CACL,KAAM,OACN,OAAQ,qBACR,MAAAC,EACA,IAAKD,EAAQ,OACb,cAAeM,EAAW,aAC5B,EAEED,GAAeA,EAAY,OAAS,EAC/B,CACL,KAAM,SACN,OAAQ,qCACR,MAAAJ,EACA,IAAKD,EAAQ,KACb,cAAeO,EAAa,aAC9B,EAGEH,GAAcA,IAAe,SAC/BH,EAAQ,SAAS,eAAeG,CAAU,EACnC,CACL,KAAM,QACN,OAAQ,4CACR,MAAAH,EACA,IAAKF,EAAIC,EAASC,CAAK,EACvB,cAAeO,EAAY,aAC7B,IAIG,CAACJ,GAAcA,IAAe,UAAYH,EACtC,CACL,KAAM,QACN,OAAQ,+EACR,MAAAA,EACA,IAAKF,EAAIC,EAASC,CAAK,EACvB,cAAeO,EAAY,aAC7B,EAMK,CACL,KAAM,SACN,OACE,+HACF,MAAO,KACP,IAAKT,EAAIC,CAAO,EAChB,cAAeS,EAAa,aAC9B,CACF,CAEA,IAAOC,EAAQ,CAAE,KAAAR,EAAK,ECpEtB,IAAIS,EAAe,UAEbC,EAAY,CAChB,MAAO,OAAO,OAAOC,CAAM,EAC3B,KAAM,OAAO,OAAOA,CAAM,EAC1B,KAAM,CAACA,EAAO,MAAOA,EAAO,YAAaA,EAAO,WAAW,EAC3D,MAAO,CAACA,EAAO,YAAaA,EAAO,WAAW,EAC9C,QAAS,CAAC,CACZ,EAEA,OAAO,OAAOA,CAAM,EAAE,QAAQC,GAAQ,CACpC,iBAAiBA,EAAMC,GAAS,CAC9B,GAAIH,EAAUD,CAAY,EAAE,SAASI,EAAM,IAAI,EAAG,CAChD,GAAM,CAAE,OAAAC,EAAQ,OAAAC,CAAO,EAAIF,EAC3B,QAAQJ,CAAY,EAAEI,EAAM,KAAM,CAAE,OAAAC,EAAQ,OAAAC,CAAO,CAAC,CACtD,CACF,CAAC,CACH,CAAC,EAED,IAAOC,EAAQ,CACb,IAAI,OAAQ,CACV,OAAOP,CACT,EACA,IAAI,MAAMQ,EAAO,CACf,OAAK,OAAO,KAAKP,CAAS,EAAE,SAASO,CAAK,IAAGA,EAAQ,WAC7CR,EAAeQ,CACzB,CACF,EC7BA,SAASC,IAAK,CACZ,OAAQ,0BAA6B,OAAO,QAAQ,SAAUC,IAC3DA,EAAK,OAAO,gBAAgB,IAAI,WAAW,CAAC,CAAC,EAAE,CAAC,EAAK,IAAOA,EAAI,GAAM,SAAS,EAAE,CACpF,CACF,CAEA,IAAOC,EAAQ,CAAE,GAAAF,EAAG,ECNpB,IAAOG,EAAQ,QCef,IAAMC,GAAa,KAAK,YAAc,CAAC,EAEjCC,EAAW,CACf,QAAAC,EACA,KAAM,GACN,aAAAC,EACA,OAAAC,EACA,OAAAC,EACA,OAAQC,EACR,sBAAuBC,EAAU,SACjC,IAAI,gBAAiB,CACnB,OAAOA,EAAU,MACnB,CACF,EAEA,SAASC,EAAoBC,EAAIC,EAAS,CACxC,MAAO,CACL,GAAAD,EACA,KAAMC,EAAQ,aAAaL,EAAO,gBAAgB,EAClD,UAAWK,EAAQ,GAAG,OAAS,EAAIA,EAAQ,GAAK,KAChD,kBAAmBC,EAAS,sBAAsBD,CAAO,EACzD,UAAW,KAAK,IAAI,EACpB,MAAOT,EAAS,MAChB,YAAaW,EAAM,OACnB,YAAaA,EAAM,OACrB,CACF,CAEA,eAAeC,GAAcC,EAAO,CAClC,IAAIJ,EACAK,EAAU,CAAC,EAEf,GAAI,CAGF,GAFAL,EAAUC,EAAS,mBAAmBG,EAAM,MAAM,EAC9C,CAACJ,GACD,CAACH,EAAU,uBAAuBO,EAAM,KAAMJ,CAAO,EAAG,OAE5D,IAAMM,EAAY,iBAAiBC,EAAM,GAAG,CAAC,GACzCC,EAASC,EAAQ,KAAKT,CAAO,EAC7BK,EAAUK,EAAAC,EAAA,GACTb,EAAoBQ,EAAWN,CAAO,GAD7B,CAEZ,OAAQQ,EAAO,KACf,QAASA,EAAO,MAAQA,EAAO,MAAM,GAAK,KAC1C,IAAKA,EAAO,GACd,GAEMI,EAAa,MAAMC,EAASjB,EAAc,MAAOI,EAAS,CAC9D,WAAY,GACZ,OAAQK,CACV,CAAC,EAED,GAAIO,EAAW,kBAAqBA,EAAW,OAAO,cAAgBR,EAAM,iBAC1E,OAAOS,EAASjB,EAAc,MAAOI,EAAS,CAC5C,OAAQ,CACN,QAAS,yBAAyBJ,EAAc,KAAK,+DACrD,OAAQgB,CACV,CACF,CAAC,EAkBH,OAfAJ,EAASC,EAAQ,KAAKT,CAAO,EAC7BK,EAAUK,EAAAC,EAAA,GACLb,EAAoBQ,EAAWN,CAAO,GADjC,CAER,OAAQQ,EAAO,KACf,QAASA,EAAO,MAAQA,EAAO,MAAM,GAAK,KAC1C,IAAKA,EAAO,GACd,GAEAM,EAAS,IAAIT,CAAO,EAEhB,CAAC,QAAS,QAAQ,EAAE,SAASG,EAAO,IAAI,GAAGJ,EAAM,eAAe,EAEpEb,EAAS,KAAO,GAChB,WAAW,IAAOA,EAAS,KAAO,GAAQ,EAAE,EAEpCiB,EAAO,KAAM,CACnB,IAAK,SACH,OAAOA,EAAO,cAAcR,EAASK,CAAO,EAC9C,IAAK,OACH,OAAOG,EAAO,cAAcR,EAASK,EAASD,CAAK,EACrD,IAAK,QACH,OAAOI,EAAO,cAAcA,EAAO,MAAOH,CAAO,EACnD,IAAK,SACH,OAAOG,EAAO,cAAcH,CAAO,CACvC,CACF,OAASU,EAAO,CACdF,EAASjB,EAAc,YAAaI,EAAS,CAC3C,OAAQU,EAAAC,EAAA,GAAKN,GAAL,CAAc,MAAAU,CAAM,EAC9B,CAAC,CACH,CACF,CAEA,KAAK,WAAaJ,EAAA,GAAKrB,IAElB,KAAK,WAAW,WAEnBO,EAAU,QAAUM,GACpBN,EAAU,SAAS,QAAS,CAAC,IAAIF,EAAO,gBAAgB,GAAG,CAAC,EAC5DE,EAAU,SAAS,SAAU,CAAC,QAAQF,EAAO,gBAAgB,GAAG,CAAC,EACjEE,EAAU,SAAS,SAAU,CAC3B,SAASF,EAAO,gBAAgB,IAChC,UAAUA,EAAO,gBAAgB,IACjC,YAAYA,EAAO,gBAAgB,GACrC,CAAC,EAED,KAAK,WAAW,SAAWJ,EAC3B,KAAK,WAAW,MAAQW,GAG1B,IAAOc,GAAQzB",
6
+ "names": ["commandEvents", "stateEvents", "allEvents", "__spreadValues", "dispatch", "name", "target", "options", "resolve", "evt", "__spreadProps", "head", "observable", "object", "parent", "proxy", "target", "key", "dispatch", "stateEvents", "value", "receiver", "index", "observable_default", "initialState", "currentState", "changedState", "signedState", "initialize", "initial", "signed", "json", "__spreadValues", "observable_default", "dispatch", "stateEvents", "event", "key", "value", "state_default", "replaceDocument", "content", "head", "tail", "headIndex", "tailIndex", "html", "append", "renderer_default", "active", "add", "payload", "remove", "id", "activity_default", "finish", "event", "dispatch", "commandEvents", "activity_default", "lifecycle_default", "frameSources", "event", "_a", "_b", "frame", "fetchOptions", "acceptHeaders", "entry", "response", "error", "dispatch", "lifecycle_default", "__spreadProps", "__spreadValues", "content", "renderer_default", "schema", "schema_default", "__spreadValues", "confirmation", "message", "isTurboMethod", "event", "isTurboForm", "element", "frame", "target", "schema_default", "shouldDelegate", "commandEvents", "confirmation_default", "events", "eventListener", "register", "eventName", "selectors", "match", "evt", "__spreadValues", "getRegisteredEventForElement", "element", "selector", "el", "isRegisteredForElement", "delegates_default", "fn", "findClosestCommand", "element", "schema_default", "findClosestFrameWithSource", "assignElementValueToPayload", "payload", "memo", "option", "buildAttributePayload", "attr", "value", "elements_default", "invokeCommand", "form", "payload", "event", "input", "form_default", "build", "urlString", "payload", "a", "url", "urls_default", "invokeCommand", "frame", "payload", "src", "__spreadValues", "urls_default", "frame_default", "invokeCommand", "element", "payload", "src", "__spreadValues", "urls_default", "method_default", "aborted", "event", "xhr", "dispatch", "lifecycle_default", "__spreadProps", "__spreadValues", "errored", "renderer_default", "error", "loaded", "content", "invokeCommand", "payload", "src", "urls_default", "ex", "message", "window_default", "src", "element", "frame", "find", "elements_default", "turboFrame", "turboMethod", "form_default", "method_default", "frame_default", "window_default", "drivers_default", "currentLevel", "logLevels", "allEvents", "name", "event", "target", "detail", "logger_default", "value", "v4", "c", "uuids_default", "version_default", "TurboBoost", "Commands", "version_default", "confirmation_default", "logger_default", "schema_default", "commandEvents", "delegates_default", "buildCommandPayload", "id", "element", "elements_default", "state_default", "invokeCommand", "event", "payload", "commandId", "uuids_default", "driver", "drivers_default", "__spreadProps", "__spreadValues", "startEvent", "dispatch", "activity_default", "error", "javascript_default"]
7
7
  }
@@ -5,7 +5,7 @@ module TurboBoost::Commands::Controller
5
5
 
6
6
  module ClassMethods
7
7
  def turbo_boost_state(&block)
8
- TurboBoost::State::Manager.add_state_override_block name, block
8
+ TurboBoost::Commands::State.assign_resolver(&block)
9
9
  end
10
10
  end
11
11
 
@@ -1,7 +1,4 @@
1
- import meta from '../meta'
2
-
3
1
  function invokeCommand(form, payload = {}, event = {}) {
4
- payload.token = meta.token
5
2
  const input = form.querySelector('input[name="turbo_boost_command"]') || document.createElement('input')
6
3
  input.type = 'hidden'
7
4
  input.name = 'turbo_boost_command'
@@ -1,4 +1,3 @@
1
- import meta from '../meta'
2
1
  import state from '../state'
3
2
  import { dispatch } from '../events'
4
3
  import lifecycle from '../lifecycle'
@@ -45,11 +44,6 @@ function invokeCommand(payload) {
45
44
  const xhr = new XMLHttpRequest()
46
45
  xhr.open('GET', urls.build(src, payload), true)
47
46
  xhr.setRequestHeader('Accept', 'text/vnd.turbo-boost.html, text/html, application/xhtml+xml')
48
- xhr.setRequestHeader('TurboBoost-Token', meta.token)
49
- state.payloadChunks.forEach((chunk, i) =>
50
- xhr.setRequestHeader(`TurboBoost-State-${i.toString().padStart(4, '0')}`, chunk)
51
- )
52
-
53
47
  xhr.addEventListener('abort', aborted)
54
48
  xhr.addEventListener('error', errored)
55
49
  xhr.addEventListener('load', loaded)
@@ -1,17 +1,32 @@
1
1
  import './turbo'
2
2
  import schema from './schema'
3
- import { dispatch, commandEvents, stateEvents } from './events'
3
+ import { dispatch, commandEvents } from './events'
4
4
  import activity from './activity'
5
5
  import confirmation from './confirmation'
6
6
  import delegates from './delegates'
7
7
  import drivers from './drivers'
8
- import meta from './meta'
9
8
  import elements from './elements'
10
9
  import lifecycle from './lifecycle'
11
10
  import logger from './logger'
12
11
  import state from './state'
13
12
  import urls from './urls'
14
13
  import uuids from './uuids'
14
+ import VERSION from './version'
15
+
16
+ const TurboBoost = self.TurboBoost || {}
17
+
18
+ const Commands = {
19
+ VERSION,
20
+ busy: false,
21
+ confirmation,
22
+ logger,
23
+ schema,
24
+ events: commandEvents,
25
+ registerEventDelegate: delegates.register,
26
+ get eventDelegates() {
27
+ return delegates.events
28
+ }
29
+ }
15
30
 
16
31
  function buildCommandPayload(id, element) {
17
32
  return {
@@ -19,7 +34,10 @@ function buildCommandPayload(id, element) {
19
34
  name: element.getAttribute(schema.commandAttribute),
20
35
  elementId: element.id.length > 0 ? element.id : null,
21
36
  elementAttributes: elements.buildAttributePayload(element),
22
- startedAt: Date.now()
37
+ startedAt: Date.now(),
38
+ token: Commands.token, // command token (used for CSRF protection)
39
+ signedState: state.signed, // server side state
40
+ clientState: state.changed // client side state (delta of optimistic updates)
23
41
  }
24
42
  }
25
43
 
@@ -67,8 +85,8 @@ async function invokeCommand(event) {
67
85
 
68
86
  if (['frame', 'window'].includes(driver.name)) event.preventDefault()
69
87
 
70
- meta.busy = true
71
- setTimeout(() => (meta.busy = false), 10)
88
+ Commands.busy = true
89
+ setTimeout(() => (Commands.busy = false), 10)
72
90
 
73
91
  switch (driver.name) {
74
92
  case 'method':
@@ -87,21 +105,7 @@ async function invokeCommand(event) {
87
105
  }
88
106
  }
89
107
 
90
- self.TurboBoost = self.TurboBoost || {}
91
-
92
- self.TurboBoost = {
93
- ...self.TurboBoost,
94
-
95
- stateEvents,
96
-
97
- get state() {
98
- return state.current
99
- },
100
-
101
- get stateDelta() {
102
- return state.delta
103
- }
104
- }
108
+ self.TurboBoost = { ...TurboBoost }
105
109
 
106
110
  if (!self.TurboBoost.Commands) {
107
111
  // wire things up and setup defaults for event delegation
@@ -114,16 +118,8 @@ if (!self.TurboBoost.Commands) {
114
118
  `textarea[${schema.commandAttribute}]`
115
119
  ])
116
120
 
117
- self.TurboBoost.Commands = {
118
- confirmation,
119
- logger,
120
- schema,
121
- events: commandEvents,
122
- registerEventDelegate: delegates.register,
123
- get eventDelegates() {
124
- return delegates.events
125
- }
126
- }
121
+ self.TurboBoost.Commands = Commands
122
+ self.TurboBoost.State = state
127
123
  }
128
124
 
129
- export default self.TurboBoost.Commands
125
+ export default Commands
@@ -1,62 +1,44 @@
1
- import meta from '../meta'
1
+ // TODO: Consider moving State to its own library
2
2
  import observable from './observable'
3
3
  import { dispatch, commandEvents, stateEvents } from '../events'
4
4
 
5
- let loadedState, currentState, changedState
6
- let loadStateTimeout
5
+ let initialState, currentState, changedState, signedState
7
6
 
8
- function loadState() {
9
- if (!meta.element) return loadStateLater()
10
- const json = atob(meta.element.dataset.state)
7
+ function initialize(initial, signed) {
8
+ const json = JSON.parse(initial)
9
+ initialState = { ...json }
10
+ signedState = signed
11
+ currentState = observable(json)
11
12
  changedState = {}
12
- currentState = observable(JSON.parse(json))
13
- loadedState = { ...currentState }
14
- delete meta.element.dataset.clientStateChange
15
13
  setTimeout(() =>
16
- dispatch(stateEvents.stateLoad, meta.element, {
14
+ dispatch(stateEvents.stateLoad, document, {
17
15
  detail: { state: currentState }
18
16
  })
19
17
  )
20
18
  }
21
19
 
22
- function loadStateLater() {
23
- clearTimeout(loadStateTimeout)
24
- loadStateTimeout = setTimeout(loadState, 10)
25
- }
26
-
27
- if (!loadedState) loadState()
28
-
29
- addEventListener('DOMContentLoaded', loadStateLater)
30
- addEventListener('load', loadStateLater)
31
- addEventListener('turbo:load', loadStateLater)
32
- addEventListener('turbo:frame-load', loadStateLater)
33
- addEventListener(commandEvents.success, loadStateLater)
34
-
35
20
  addEventListener(stateEvents.stateChange, event => {
36
- changedState = {}
37
21
  for (const [key, value] of Object.entries(currentState))
38
- if (loadedState[key] !== value) changedState[key] = value
39
- meta.element.dataset.clientStateChange = true
40
- meta.element.dataset.state = btoa(JSON.stringify(currentState))
22
+ if (initialState[key] !== value) changedState[key] = value
41
23
  })
42
24
 
43
25
  export default {
26
+ initialize,
44
27
  events: stateEvents,
45
28
 
29
+ get initial() {
30
+ return initialState
31
+ },
32
+
46
33
  get current() {
47
34
  return currentState
48
35
  },
49
36
 
50
- get delta() {
37
+ get changed() {
51
38
  return changedState
52
39
  },
53
40
 
54
- // The UI state changes are split into chunks and sent to the server in an HTTP request header.
55
- // Max size for an HTTP header is around 4k or 4,000 bytes.
56
- // A Base64 character is an 8-bit-padded ASCII character... or 1 byte
57
- //
58
- // SEE: lib/state.rb - for info on how `state` is serialized/deserialized
59
- get payloadChunks() {
60
- return btoa(JSON.stringify(changedState)).match(/.{1,2000}/g)
41
+ get signed() {
42
+ return signedState
61
43
  }
62
44
  }
@@ -1,4 +1,3 @@
1
- import meta from '../meta'
2
1
  import { dispatch, stateEvents as events } from '../events'
3
2
 
4
3
  let head
@@ -9,13 +8,13 @@ function observable(object, parent = null) {
9
8
  const proxy = new Proxy(object, {
10
9
  deleteProperty(target, key) {
11
10
  delete target[key]
12
- dispatch(events.stateChange, meta.element, { detail: { state: head } })
11
+ dispatch(events.stateChange, document, { detail: { state: head } })
13
12
  return true
14
13
  },
15
14
 
16
15
  set(target, key, value, receiver) {
17
16
  target[key] = observable(value, this)
18
- dispatch(events.stateChange, meta.element, { detail: { state: head } })
17
+ dispatch(events.stateChange, document, { detail: { state: head } })
19
18
  return true
20
19
  }
21
20
  })
@@ -1,4 +1,3 @@
1
- import meta from './meta'
2
1
  import state from './state'
3
2
  import renderer from './renderer'
4
3
  import { dispatch } from './events'
@@ -12,17 +11,11 @@ addEventListener('turbo:before-fetch-request', event => {
12
11
  const { fetchOptions } = event.detail
13
12
 
14
13
  // command invoked and busy
15
- if (meta.busy) {
14
+ if (self.TurboBoost?.Commands?.busy) {
16
15
  let acceptHeaders = ['text/vnd.turbo-boost.html', fetchOptions.headers['Accept']]
17
16
  acceptHeaders = acceptHeaders.filter(entry => entry && entry.trim().length > 0).join(', ')
18
17
  fetchOptions.headers['Accept'] = acceptHeaders
19
- fetchOptions.headers['TurboBoost-Token'] = meta.token
20
18
  }
21
-
22
- // always send state
23
- state.payloadChunks.forEach((chunk, i) => {
24
- fetchOptions.headers[`TurboBoost-State-${i.toString().padStart(4, '0')}`] = chunk
25
- })
26
19
  })
27
20
 
28
21
  // fires after receiving a turbo HTTP response
@@ -2,7 +2,7 @@ function build(urlString, payload = {}) {
2
2
  const a = document.createElement('a')
3
3
  a.href = urlString
4
4
  const url = new URL(a)
5
- url.searchParams.set('turbo_boost_command', JSON.stringify(payload))
5
+ url.searchParams.set('tbc', JSON.stringify(payload))
6
6
  return url
7
7
  }
8
8
 
@@ -0,0 +1 @@
1
+ export default '0.1.1'