turbo_reflex 0.0.10 → 0.0.12

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5de4d9a342e72de153e009f60a93152852d6f32f9ee8ad03f51c0b3b2f1fb366
4
- data.tar.gz: 2690179e8438f3d02ca72e49edcccfa94fb929b79033a31d5310b8404617458f
3
+ metadata.gz: 4f42ae3edf4f0aa9780d19639ffa9a33f8feffcd192804e58e41ae06fe1a4f34
4
+ data.tar.gz: c924130978b1c3f62c6d0cac2d41a6272dc58ed91808d5cd439aeb3f86938273
5
5
  SHA512:
6
- metadata.gz: f6053af2b8d8b3bdb64a00ed63ea542b9aec4b4bfa6977e7c3dda863ced8046800e3ca8cdb874febf60e1219f559f3d960ba09538fb7b13b0807338e070bb156
7
- data.tar.gz: d83f0fd6ec591ebb6e577b4923d99a5fa18da7c67614f77f9ad2b4ccad05f1183d4df9a8c88e7b93a01c447a27f68358cb9b6b9363c0471ebf52710fe2d36791
6
+ metadata.gz: 601f6e33fd473f9e440d5698a5686ee18a168197d5465af70d78af20174b0a635f93637ec6e671fd937a1baf2d40d24c516800d2722673b364f18d2e0520552e
7
+ data.tar.gz: df26c274b5f74bed30332d1e0af7611a609ab2cbc0731dee1c510931fa6b87fe1a2bc2e4453ecce827916b322924c92f60de006ae0251c046b1fab934a190aa8
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- turbo_reflex (0.0.10)
4
+ turbo_reflex (0.0.12)
5
5
  rails (>= 6.1)
6
6
  turbo-rails (>= 1.1)
7
7
  turbo_ready (>= 0.1)
@@ -134,7 +134,7 @@ GEM
134
134
  net-protocol
135
135
  net-protocol (0.1.3)
136
136
  timeout
137
- net-smtp (0.3.2)
137
+ net-smtp (0.3.3)
138
138
  net-protocol
139
139
  nio4r (2.5.8)
140
140
  nokogiri (1.13.9-aarch64-linux)
@@ -203,7 +203,7 @@ GEM
203
203
  rubocop-ast (>= 1.20.1, < 2.0)
204
204
  ruby-progressbar (~> 1.7)
205
205
  unicode-display_width (>= 1.4.0, < 3.0)
206
- rubocop-ast (1.22.0)
206
+ rubocop-ast (1.23.0)
207
207
  parser (>= 3.1.1.0)
208
208
  rubocop-performance (1.14.3)
209
209
  rubocop (>= 1.7.0, < 2.0)
@@ -222,20 +222,19 @@ GEM
222
222
  actionpack (>= 5.2)
223
223
  activesupport (>= 5.2)
224
224
  sprockets (>= 3.0.0)
225
- sqlite3 (1.5.3-aarch64-linux)
226
225
  sqlite3 (1.5.3-arm64-darwin)
227
226
  standard (1.16.1)
228
227
  rubocop (= 1.35.1)
229
228
  rubocop-performance (= 1.14.3)
230
229
  standardrb (1.0.1)
231
230
  standard
232
- tailwindcss-rails (2.0.14-aarch64-linux)
231
+ tailwindcss-rails (2.0.17-aarch64-linux)
233
232
  railties (>= 6.0.0)
234
- tailwindcss-rails (2.0.14-arm64-darwin)
233
+ tailwindcss-rails (2.0.17-arm64-darwin)
235
234
  railties (>= 6.0.0)
236
235
  thor (1.2.1)
237
236
  timeout (0.3.0)
238
- turbo-rails (1.3.1)
237
+ turbo-rails (1.3.2)
239
238
  actionpack (>= 6.0.0)
240
239
  activejob (>= 6.0.0)
241
240
  railties (>= 6.0.0)
@@ -263,7 +262,7 @@ GEM
263
262
  nokogiri (~> 1.8)
264
263
  yard (0.9.28)
265
264
  webrick (~> 1.7.0)
266
- zeitwerk (2.6.1)
265
+ zeitwerk (2.6.4)
267
266
 
268
267
  PLATFORMS
269
268
  aarch64-linux
@@ -294,4 +293,4 @@ DEPENDENCIES
294
293
  webdrivers
295
294
 
296
295
  BUNDLED WITH
297
- 2.3.21
296
+ 2.3.5
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-917-47d299.svg" />
11
+ <img alt="Lines of Code" src="https://img.shields.io/badge/loc-1098-47d299.svg" />
12
12
  </a>
13
13
  <a href="https://codeclimate.com/github/hopsoft/turbo_reflex/maintainability">
14
14
  <img src="https://api.codeclimate.com/v1/badges/fe1162a742fe83a4fdfd/maintainability" />
data/Rakefile CHANGED
@@ -10,7 +10,13 @@ load "rails/tasks/statistics.rake"
10
10
 
11
11
  Rake::TestTask.new do |test|
12
12
  test.libs << "test"
13
- test.test_files = FileList["test/**/*_test.rb"]
13
+
14
+ test.test_files = if ARGV.length > 1
15
+ FileList[ARGV[1..]]
16
+ else
17
+ FileList["test/**/*_test.rb"]
18
+ end
19
+
14
20
  test.warning = false
15
21
  end
16
22
 
@@ -1,2 +1,2 @@
1
- var v=class{get element(){return document.querySelector('meta[name="turbo-reflex"]')}get token(){return this.element.getAttribute("content")}get busy(){return this.element.dataset.busy==="true"}set busy(t){return this.element.dataset.busy=!!t}get uiStateBase64(){return this.element.dataset.uiState}get uiStateBase64Chunks(){return this.uiStateBase64.match(/.{1,2000}/g)}get uiStateJSON(){return atob(this.uiStateBase64)}get uiState(){return JSON.parse(this.uiStateJSON)}},i=new v;function N(e){let t="<html",r="</html",n=e.indexOf(t),s=e.lastIndexOf(r);if(n>=0&&s>=0){let $=e.slice(e.indexOf(">",n)+1,s);document.documentElement.innerHTML=$}}function j(e){document.body.insertAdjacentHTML("beforeend",e)}var l={append:j,replaceDocument:N};var b={};function q(e){b[e.id]=e}function H(e){delete b[e]}var p={add:q,remove:H,get reflexes(){return[...Object.values(b)]},get length(){return Object.keys(b).length}};var f={start:"turbo-reflex:start",success:"turbo-reflex:success",finish:"turbo-reflex:finish",abort:"turbo-reflex:abort",clientError:"turbo-reflex:client-error",serverError:"turbo-reflex:server-error"};function x(e,t=document,r={},n=!1){try{t=t||document;let s=new CustomEvent(e,{detail:r,cancelable:!1,bubbles:!0});t.dispatchEvent(s)}catch(s){if(n)throw s;x(f.clientError,t,{error:s,...r},!0)}}function X(e={}){x(f.clientError,window,e,!0)}function A(e){e.detail.endedAt=new Date().getTime(),e.detail.milliseconds=e.detail.endedAt-e.detail.startedAt,setTimeout(()=>x(f.finish,e.target,e.detail),20)}addEventListener(f.serverError,A);addEventListener(f.success,A);addEventListener(f.finish,e=>p.remove(e.detail.id),!0);var o={dispatch:x,dispatchClientError:X,events:f};var g={};addEventListener("turbo:before-fetch-request",e=>{let t=e.target.closest("turbo-frame"),{fetchOptions:r}=e.detail;if(i.busy){let n=["text/vnd.turbo-reflex.html",r.headers.Accept];n=n.filter(s=>s&&s.trim().length>0).join(", "),r.headers.Accept=n}r.headers["TurboReflex-Token"]=i.token,i.uiStateBase64Chunks.forEach((n,s)=>r.headers[`TurboReflex-UiState-${s.toString().padStart(6,"0")}`]=n)});addEventListener("turbo:before-fetch-response",e=>{let t=e.target.closest("turbo-frame"),{fetchResponse:r}=e.detail;if(t&&(g[t.id]=t.src),r.header("TurboReflex")){if(r.statusCode<200||r.statusCode>399){let n=`Server returned a ${r.statusCode} status code! TurboReflex requires 2XX-3XX status codes.`;o.dispatchClientError({...e.detail,error:n})}r.header("TurboReflex")==="Append"&&(e.preventDefault(),r.responseText.then(n=>l.append(n)))}});addEventListener("turbo:frame-load",e=>{let t=e.target.closest("turbo-frame");t.dataset.turboReflexSrc=g[t.id]||t.src||t.dataset.turboReflexSrc,delete g[t.id]});var B={frameAttribute:"data-turbo-frame",methodAttribute:"data-turbo-method",reflexAttribute:"data-turbo-reflex"},a={...B};var h={},T;function I(e,t){h[e]=t,document.addEventListener(e,T,!0)}function _(e){return Object.keys(h).find(t=>!!h[t].find(r=>Array.from(document.querySelectorAll(r)).find(n=>n===e)))}function F(e,t){return e===_(t)}var u={events:h,register:I,isRegisteredForElement:F,set handler(e){T=e}};function J(e){return e.closest(`[${a.reflexAttribute}]`)}function P(e){return e.closest("turbo-frame")}function U(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,n)=>(n.selected&&r.push(n.value),r),[])}function M(e){let t=Array.from(e.attributes).reduce((r,n)=>{let s=n.value;return r[n.name]=s,r},{});return t.tag=e.tagName,t.checked=!!e.checked,t.disabled=!!e.disabled,U(e,t),delete t.class,delete t.action,delete t.href,delete t[a.reflexAttribute],delete t[a.frameAttribute],t}var d={buildAttributePayload:M,findClosestReflex:J,findClosestFrame:P};function V(e,t={}){t.token=i.token;let r=document.createElement("input");r.type="hidden",r.name="turbo_reflex",r.value=JSON.stringify(t),e.appendChild(r)}var S={invokeReflex:V};function G(e,t={}){let r=document.createElement("a");r.href=e;let n=new URL(r);return n.searchParams.set("turbo_reflex",JSON.stringify(t)),n}var c={build:G};function z(e,t){let r=t.src;t={...t},delete t.src,e.src=c.build(r,t)}var R={invokeReflex:z};function K(e,t={}){let r=t.src;t={...t},delete t.src,delete t.href,e.setAttribute("href",c.build(r,t))}var w={invokeReflex:K};function Q(e){let t=e.target;o.dispatch(o.events.abort,window,{xhr:t,...e.detail})}function E(e){let t=e.target;t.getResponseHeader("TurboReflex")==="Append"?l.append(t.responseText):l.replaceDocument(t.responseText);let r=`Server returned a ${t.status} status code! TurboReflex requires 2XX-3XX status codes.`;o.dispatchClientError({xhr:t,...e.detail,error:r})}function W(e){let t=e.target;if(t.status<200||t.status>399)return E(e);let r=t.responseText;t.getResponseHeader("TurboReflex")==="Append"?l.append(t.responseText):l.replaceDocument(t.responseText)}function Y(e){let t=e.src;e={...e},delete e.src;try{let r=new XMLHttpRequest;r.open("GET",c.build(t,e),!0),r.setRequestHeader("Accept","text/vnd.turbo-reflex.html, text/html, application/xhtml+xml"),r.setRequestHeader("TurboReflex-Token",i.token),i.uiStateBase64Chunks.forEach((n,s)=>r.setRequestHeader(`TurboReflex-UiState-${s.toString().padStart(6,"0")}`,n)),r.addEventListener("abort",Q),r.addEventListener("error",E),r.addEventListener("load",W),r.send()}catch(r){let n=`Unexpected error sending HTTP request! ${r.message}`;E(r,{detail:{message:n}})}}var y={invokeReflex:Y};function k(e,t){return t=t||{dataset:{}},e.href||t.src||t.dataset.turboReflexSrc||location.href}function Z(e){let t=d.findClosestFrame(e),{turboFrame:r,turboMethod:n}=e.dataset;return e.tagName.toLowerCase()==="form"?{name:"form",reason:"Element is a form.",frame:t,src:e.action,invokeReflex:S.invokeReflex}:n&&n.length>0?{name:"method",reason:"Element defines data-turbo-method.",frame:t,src:e.href,invokeReflex:w.invokeReflex}:r&&r!=="_self"?(t=document.getElementById(r),{name:"frame",reason:"element targets a frame that is not _self",frame:t,src:k(e,t),invokeReflex:R.invokeReflex}):(!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:k(e,t),invokeReflex:R.invokeReflex}:{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:k(e),invokeReflex:y.invokeReflex}}var L={find:Z};var m="unknown",O={debug:Object.values(o.events),info:Object.values(o.events),warn:[o.events.abort,o.events.clientError,o.events.serverError],error:[o.events.clientError,o.events.serverError],unknown:[]};Object.values(o.events).forEach(e=>{addEventListener(e,t=>{O[m].includes(t.type)&&console[m==="debug"?"log":m](t.type,t.detail)})});var C={get level(){return m},set level(e){return Object.keys(O).includes(e)||(e="unknown"),m=e}};function ee(){return([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g,e=>(e^crypto.getRandomValues(new Uint8Array(1))[0]&15>>e/4).toString(16))}var D={v4:ee};function te(e){let t,r={};try{if(t=d.findClosestReflex(e.target),!t||!u.isRegisteredForElement(e.type,t))return;let n=L.find(t);switch(r={id:`reflex-${D.v4()}`,name:t.dataset.turboReflex,driver:n.name,src:n.src,frameId:n.frame?n.frame.id:null,elementId:t.id.length>0?t.id:null,elementAttributes:d.buildAttributePayload(t),startedAt:new Date().getTime()},p.add(r),o.dispatch(o.events.start,t,r),["frame","window"].includes(n.name)&&e.preventDefault(),i.busy=!0,setTimeout(()=>i.busy=!1,10),n.name){case"method":return n.invokeReflex(t,r);case"form":return n.invokeReflex(t,r);case"frame":return n.invokeReflex(n.frame,r);case"window":return n.invokeReflex(r)}}catch(n){o.dispatch(o.events.clientError,t,{error:n,...r})}}u.handler=te;u.register("change",[`input[${a.reflexAttribute}]`,`select[${a.reflexAttribute}]`,`textarea[${a.reflexAttribute}]`]);u.register("submit",[`form[${a.reflexAttribute}]`]);u.register("click",[`[${a.reflexAttribute}]`]);var Ke={schema:a,logger:C,registerEventDelegate:u.register,get eventDelegates(){return{...u.events}},get lifecycleEvents(){return[...Object.values(o.events)]}};export{Ke as default};
1
+ var L=class{get element(){return document.querySelector('meta[name="turbo-reflex"]')}get token(){return this.element.getAttribute("content")}get busy(){return this.element.dataset.busy==="true"}set busy(t){return this.element.dataset.busy=!!t}},s=new L;var d={start:"turbo-reflex:start",success:"turbo-reflex:success",finish:"turbo-reflex:finish",abort:"turbo-reflex:abort",clientError:"turbo-reflex:client-error",serverError:"turbo-reflex:server-error"},f={beforeStateChange:"turbo-reflex:before-state-change",stateChange:"turbo-reflex:state-change"},l={...d,...f};function a(e,t=document,r={},n=!1){try{t=t||document;let o=new CustomEvent(e,{detail:r,cancelable:!1,bubbles:!0});t.dispatchEvent(o)}catch(o){if(n)throw o;a(d.clientError,t,{error:o,...r},!0)}}var x;function g(e,t=null){if(!e||typeof e!="object")return e;let r=new Proxy(e,{deleteProperty(n,o){return a(f.beforeStateChange,s.element,{state:x}),delete n[o],a(f.stateChange,s.element,{state:x}),!0},set(n,o,S,me){return a(f.beforeStateChange,s.element,{state:x}),n[o]=g(S,this),a(f.stateChange,s.element,{state:x}),!0}});if(Array.isArray(e))e.forEach((n,o)=>e[o]=g(n,r));else if(typeof e=="object")for(let[n,o]of Object.entries(e))e[n]=g(o,r);return t||(x=r),r}var q=g;var O,p,R,E;function H(){let e=atob(s.element.dataset.state);R={},O=p=q(JSON.parse(e))}function w(){E&&E.disconnect(),E=new MutationObserver(H),E.observe(s.element,{attributes:!0,attributeFilter:["data-state"]})}addEventListener("DOMContentLoaded",H);addEventListener("DOMContentLoaded",w);addEventListener("turbo:load",w);addEventListener("turbo:frame-load",w);addEventListener(f.beforeStateChange,e=>O=JSON.parse(JSON.stringify(p)));addEventListener(f.stateChange,e=>{R={};for(let[t,r]of Object.entries(p))O[t]!==r&&(R[t]=r);s.element.dataset.state=btoa(JSON.stringify(p))});var y={events:f,get payloadChunks(){return btoa(JSON.stringify(R)).match(/.{1,2000}/g)}};function V(e){let t="<html",r="</html",n=e.indexOf(t),o=e.lastIndexOf(r);if(n>=0&&o>=0){let S=e.slice(e.indexOf(">",n)+1,o);document.documentElement.innerHTML=S}}function B(e){document.body.insertAdjacentHTML("beforeend",e)}var m={append:B,replaceDocument:V};var k={};function G(e){k[e.id]=e}function z(e){delete k[e]}var A={add:G,remove:z,get reflexes(){return[...Object.values(k)]},get length(){return Object.keys(k).length}};function X(e){e.detail.endedAt=new Date().getTime(),e.detail.milliseconds=e.detail.endedAt-e.detail.startedAt,setTimeout(()=>a(d.finish,e.target,e.detail),20)}addEventListener(d.serverError,X);addEventListener(d.success,X);addEventListener(d.finish,e=>A.remove(e.detail.id),!0);var u={events:d};var C={};addEventListener("turbo:before-fetch-request",e=>{let t=e.target.closest("turbo-frame"),{fetchOptions:r}=e.detail;if(s.busy){let n=["text/vnd.turbo-reflex.html",r.headers.Accept];n=n.filter(o=>o&&o.trim().length>0).join(", "),r.headers.Accept=n,r.headers["TurboReflex-Token"]=s.token}y.payloadChunks.forEach((n,o)=>r.headers[`TurboReflex-State-${o.toString().padStart(4,"0")}`]=n)});addEventListener("turbo:before-fetch-response",e=>{let t=e.target.closest("turbo-frame"),{fetchResponse:r}=e.detail;if(t&&(C[t.id]=t.src),r.header("TurboReflex")){if(r.statusCode<200||r.statusCode>399){let n=`Server returned a ${r.statusCode} status code! TurboReflex requires 2XX-3XX status codes.`;a(u.events.clientError,document,{...e.detail,error:n},!0)}r.header("TurboReflex")==="Append"&&(e.preventDefault(),r.responseText.then(n=>m.append(n)))}});addEventListener("turbo:frame-load",e=>{let t=e.target.closest("turbo-frame");t.dataset.turboReflexSrc=C[t.id]||t.src||t.dataset.turboReflexSrc,delete C[t.id]});var K={frameAttribute:"data-turbo-frame",methodAttribute:"data-turbo-method",reflexAttribute:"data-turbo-reflex"},i={...K};var T={},F;function Q(e,t){T[e]=t,document.addEventListener(e,F,!0)}function W(e){return Object.keys(T).find(t=>!!T[t].find(r=>Array.from(document.querySelectorAll(r)).find(n=>n===e)))}function Y(e,t){return e===W(t)}var c={events:T,register:Q,isRegisteredForElement:Y,set handler(e){F=e}};function Z(e){return e.closest(`[${i.reflexAttribute}]`)}function ee(e){return e.closest("turbo-frame")}function te(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,n)=>(n.selected&&r.push(n.value),r),[])}function re(e){let t=Array.from(e.attributes).reduce((r,n)=>{let o=n.value;return r[n.name]=o,r},{});return t.tag=e.tagName,t.checked=!!e.checked,t.disabled=!!e.disabled,te(e,t),delete t.class,delete t.action,delete t.href,delete t[i.reflexAttribute],delete t[i.frameAttribute],t}var v={buildAttributePayload:re,findClosestReflex:Z,findClosestFrame:ee};function ne(e,t={}){t.token=s.token;let r=document.createElement("input");r.type="hidden",r.name="turbo_reflex",r.value=JSON.stringify(t),e.appendChild(r)}var I={invokeReflex:ne};function oe(e,t={}){let r=document.createElement("a");r.href=e;let n=new URL(r);return n.searchParams.set("turbo_reflex",JSON.stringify(t)),n}var b={build:oe};function se(e,t){let r=t.src;t={...t},delete t.src,e.src=b.build(r,t)}var D={invokeReflex:se};function ae(e,t={}){let r=t.src;t={...t},delete t.src,delete t.href,e.setAttribute("href",b.build(r,t))}var J={invokeReflex:ae};function ie(e){let t=e.target;a(u.events.abort,document,{xhr:t,...e.detail})}function N(e){let t=e.target;t.getResponseHeader("TurboReflex")==="Append"?m.append(t.responseText):m.replaceDocument(t.responseText);let r=`Server returned a ${t.status} status code! TurboReflex requires 2XX-3XX status codes.`;a(u.events.clientError,document,{xhr:t,...e.detail,error:r},!0)}function fe(e){let t=e.target;if(t.status<200||t.status>399)return N(e);let r=t.responseText;t.getResponseHeader("TurboReflex")==="Append"?m.append(t.responseText):m.replaceDocument(t.responseText)}function le(e){let t=e.src;e={...e},delete e.src;try{let r=new XMLHttpRequest;r.open("GET",b.build(t,e),!0),r.setRequestHeader("Accept","text/vnd.turbo-reflex.html, text/html, application/xhtml+xml"),r.setRequestHeader("TurboReflex-Token",s.token),y.payloadChunks.forEach((n,o)=>r.setRequestHeader(`TurboReflex-State-${o.toString().padStart(4,"0")}`,n)),r.addEventListener("abort",ie),r.addEventListener("error",N),r.addEventListener("load",fe),r.send()}catch(r){let n=`Unexpected error sending HTTP request! ${r.message}`;N(r,{detail:{message:n}})}}var P={invokeReflex:le};function $(e,t){return t=t||{dataset:{}},e.href||t.src||t.dataset.turboReflexSrc||location.href}function ue(e){let t=v.findClosestFrame(e),{turboFrame:r,turboMethod:n}=e.dataset;return e.tagName.toLowerCase()==="form"?{name:"form",reason:"Element is a form.",frame:t,src:e.action,invokeReflex:I.invokeReflex}:n&&n.length>0?{name:"method",reason:"Element defines data-turbo-method.",frame:t,src:e.href,invokeReflex:J.invokeReflex}:r&&r!=="_self"?(t=document.getElementById(r),{name:"frame",reason:"element targets a frame that is not _self",frame:t,src:$(e,t),invokeReflex:D.invokeReflex}):(!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),invokeReflex:D.invokeReflex}:{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),invokeReflex:P.invokeReflex}}var _={find:ue};var h="unknown",j={debug:Object.values(l),info:Object.values(l),warn:[l.abort,l.clientError,l.serverError],error:[l.clientError,l.serverError],unknown:[]};Object.values(l).forEach(e=>{addEventListener(e,t=>{j[h].includes(t.type)&&console[h==="debug"?"log":h](t.type,t.detail)})});var M={get level(){return h},set level(e){return Object.keys(j).includes(e)||(e="unknown"),h=e}};function de(){return([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g,e=>(e^crypto.getRandomValues(new Uint8Array(1))[0]&15>>e/4).toString(16))}var U={v4:de};function ce(e){let t,r={};try{if(t=v.findClosestReflex(e.target),!t||!c.isRegisteredForElement(e.type,t))return;let n=_.find(t);switch(r={id:`reflex-${U.v4()}`,name:t.dataset.turboReflex,driver:n.name,src:n.src,frameId:n.frame?n.frame.id:null,elementId:t.id.length>0?t.id:null,elementAttributes:v.buildAttributePayload(t),startedAt:new Date().getTime()},A.add(r),a(u.events.start,t,r),["frame","window"].includes(n.name)&&e.preventDefault(),s.busy=!0,setTimeout(()=>s.busy=!1,10),n.name){case"method":return n.invokeReflex(t,r);case"form":return n.invokeReflex(t,r);case"frame":return n.invokeReflex(n.frame,r);case"window":return n.invokeReflex(r)}}catch(n){a(u.events.clientError,t,{error:n,...r})}}c.handler=ce;c.register("change",[`input[${i.reflexAttribute}]`,`select[${i.reflexAttribute}]`,`textarea[${i.reflexAttribute}]`]);c.register("submit",[`form[${i.reflexAttribute}]`]);c.register("click",[`[${i.reflexAttribute}]`]);var yt=self.TurboReflex={logger:M,schema:i,registerEventDelegate:c.register,get eventDelegates(){return{...c.events}},get lifecycleEvents(){return[...Object.values(u.events)]},get state(){return p}};export{yt as default};
2
2
  //# sourceMappingURL=turbo_reflex.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../../javascript/meta.js", "../../javascript/renderer.js", "../../javascript/activity.js", "../../javascript/lifecycle.js", "../../javascript/turbo.js", "../../javascript/schema.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-reflex\"]')\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 get uiStateBase64 () {\n return this.element.dataset.uiState\n }\n\n // UI state gets 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/ui_state.rb - for info on how UiState is serialized/deserialized\n get uiStateBase64Chunks () {\n return this.uiStateBase64.match(/.{1,2000}/g)\n }\n\n get uiStateJSON () {\n return atob(this.uiStateBase64)\n }\n\n get uiState () {\n return JSON.parse(this.uiStateJSON)\n }\n}\n\nexport default new Meta()\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 reflexes () {\n return [...Object.values(active)]\n },\n get length () {\n return Object.keys(active).length\n }\n}\n", "import activity from './activity'\n\nconst events = {\n start: 'turbo-reflex:start',\n success: 'turbo-reflex:success',\n finish: 'turbo-reflex:finish',\n abort: 'turbo-reflex:abort',\n clientError: 'turbo-reflex:client-error',\n serverError: 'turbo-reflex:server-error'\n}\n\nfunction dispatch (name, target = document, detail = {}, raise = false) {\n try {\n target = target || document\n const event = new CustomEvent(name, {\n detail,\n cancelable: false,\n bubbles: true\n })\n target.dispatchEvent(event)\n } catch (error) {\n if (raise) throw error\n dispatch(events.clientError, target, { error, ...detail }, true)\n }\n}\n\nfunction dispatchClientError (detail = {}) {\n dispatch(events.clientError, window, detail, true)\n}\n\nfunction finish (event) {\n event.detail.endedAt = new Date().getTime()\n event.detail.milliseconds = event.detail.endedAt - event.detail.startedAt\n setTimeout(() => dispatch(events.finish, event.target, event.detail), 20)\n}\n\naddEventListener(events.serverError, finish)\naddEventListener(events.success, finish)\naddEventListener(events.finish, event => activity.remove(event.detail.id), true)\n\nexport default {\n dispatch,\n dispatchClientError,\n events\n}\n", "import meta from './meta'\nimport renderer from './renderer'\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 if (meta.busy) {\n let acceptHeaders = [\n 'text/vnd.turbo-reflex.html',\n fetchOptions.headers['Accept']\n ]\n acceptHeaders = acceptHeaders\n .filter(entry => entry && entry.trim().length > 0)\n .join(', ')\n fetchOptions.headers['Accept'] = acceptHeaders\n }\n fetchOptions.headers['TurboReflex-Token'] = meta.token\n meta.uiStateBase64Chunks.forEach(\n (chunk, i) =>\n (fetchOptions.headers[\n `TurboReflex-UiState-${i.toString().padStart(6, '0')}`\n ] = 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('TurboReflex')) {\n if (response.statusCode < 200 || response.statusCode > 399) {\n const error = `Server returned a ${response.statusCode} status code! TurboReflex requires 2XX-3XX status codes.`\n lifecycle.dispatchClientError({ ...event.detail, error })\n }\n\n if (response.header('TurboReflex') === '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.turboReflexSrc =\n frameSources[frame.id] || frame.src || frame.dataset.turboReflexSrc\n delete frameSources[frame.id]\n})\n", "const schema = {\n frameAttribute: 'data-turbo-frame',\n methodAttribute: 'data-turbo-method',\n reflexAttribute: 'data-turbo-reflex'\n}\n\nexport default { ...schema }\n", "const events = {}\nlet eventListener\n\nfunction register (eventName, selectors) {\n events[eventName] = selectors\n document.addEventListener(eventName, eventListener, true)\n}\n\nfunction getRegisteredEventNameForElement (element) {\n return Object.keys(events).find(eventName => {\n return !!events[eventName].find(selector =>\n Array.from(document.querySelectorAll(selector)).find(el => el === element)\n )\n })\n}\n\nfunction isRegisteredForElement (eventName, element) {\n return eventName === getRegisteredEventNameForElement(element)\n}\n\nexport default {\n events,\n register,\n isRegisteredForElement,\n set handler (fn) {\n eventListener = fn\n }\n}\n", "import schema from './schema.js'\nimport lifecycle from './lifecycle'\n\nfunction findClosestReflex (element) {\n return element.closest(`[${schema.reflexAttribute}]`)\n}\n\nfunction findClosestFrame (element) {\n return element.closest('turbo-frame')\n}\n\nfunction assignElementValueToPayload (element, payload = {}) {\n if (element.tagName.toLowerCase() !== 'select')\n return (payload.value = element.value || null)\n\n if (!element.multiple)\n 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.reflexAttribute]\n delete payload[schema.frameAttribute]\n\n return payload\n}\n\nexport default {\n buildAttributePayload,\n findClosestReflex,\n findClosestFrame\n}\n", "import meta from '../meta'\n\nfunction invokeReflex (form, payload = {}) {\n payload.token = meta.token\n const input = document.createElement('input')\n input.type = 'hidden'\n input.name = 'turbo_reflex'\n input.value = JSON.stringify(payload)\n form.appendChild(input)\n}\n\nexport default { invokeReflex }\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_reflex', JSON.stringify(payload))\n return url\n}\n\nexport default { build }\n", "import urls from '../urls'\n\nfunction invokeReflex (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 { invokeReflex }\n", "import urls from '../urls'\n\nfunction invokeReflex (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 { invokeReflex }\n", "import meta from '../meta'\nimport lifecycle from '../lifecycle'\nimport urls from '../urls'\nimport renderer from '../renderer'\n\nfunction aborted (event) {\n const xhr = event.target\n lifecycle.dispatch(lifecycle.events.abort, window, { xhr, ...event.detail })\n}\n\nfunction errored (event) {\n const xhr = event.target\n\n xhr.getResponseHeader('TurboReflex') === 'Append'\n ? renderer.append(xhr.responseText)\n : renderer.replaceDocument(xhr.responseText)\n\n const error = `Server returned a ${xhr.status} status code! TurboReflex requires 2XX-3XX status codes.`\n lifecycle.dispatchClientError({ xhr, ...event.detail, error })\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 xhr.getResponseHeader('TurboReflex') === 'Append'\n ? renderer.append(xhr.responseText)\n : renderer.replaceDocument(xhr.responseText)\n}\n\nfunction invokeReflex (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(\n 'Accept',\n 'text/vnd.turbo-reflex.html, text/html, application/xhtml+xml'\n )\n xhr.setRequestHeader('TurboReflex-Token', meta.token)\n meta.uiStateBase64Chunks.forEach((chunk, i) =>\n xhr.setRequestHeader(\n `TurboReflex-UiState-${i.toString().padStart(6, '0')}`,\n chunk\n )\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 { invokeReflex }\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 (\n element.href || frame.src || frame.dataset.turboReflexSrc || location.href\n )\n}\n\nfunction find (element) {\n let frame = elements.findClosestFrame(element)\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 invokeReflex: formDriver.invokeReflex\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 invokeReflex: methodDriver.invokeReflex\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 invokeReflex: frameDriver.invokeReflex\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:\n 'element does NOT target a frame or targets _self and is contained by a frame',\n frame,\n src: src(element, frame),\n invokeReflex: frameDriver.invokeReflex\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 invokeReflex: windowDriver.invokeReflex\n }\n}\n\nexport default { find }\n", "import lifecycle from './lifecycle'\n\nlet currentLevel = 'unknown'\n\nconst logLevels = {\n debug: Object.values(lifecycle.events),\n info: Object.values(lifecycle.events),\n warn: [\n lifecycle.events.abort,\n lifecycle.events.clientError,\n lifecycle.events.serverError\n ],\n error: [lifecycle.events.clientError, lifecycle.events.serverError],\n unknown: []\n}\n\nObject.values(lifecycle.events).forEach(name => {\n addEventListener(name, event => {\n if (logLevels[currentLevel].includes(event.type)) {\n const level = currentLevel === 'debug' ? 'log' : currentLevel\n console[level](event.type, event.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 (\n c ^\n (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (c / 4)))\n ).toString(16)\n )\n}\n\nexport default { v4 }\n", "import './turbo'\nimport schema from './schema.js'\nimport activity from './activity'\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 urls from './urls'\nimport uuids from './uuids'\n\nfunction invokeReflex (event) {\n let element\n let payload = {}\n\n try {\n element = elements.findClosestReflex(event.target)\n if (!element) return\n if (!delegates.isRegisteredForElement(event.type, element)) return\n\n const driver = drivers.find(element)\n\n // payload sent to server (also used for lifecycle event.detail)\n payload = {\n id: `reflex-${uuids.v4()}`,\n name: element.dataset.turboReflex,\n driver: driver.name,\n src: driver.src,\n frameId: driver.frame ? driver.frame.id : null,\n elementId: element.id.length > 0 ? element.id : null,\n elementAttributes: elements.buildAttributePayload(element),\n startedAt: new Date().getTime()\n }\n\n activity.add(payload)\n lifecycle.dispatch(lifecycle.events.start, element, 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.invokeReflex(element, payload)\n case 'form':\n return driver.invokeReflex(element, payload)\n case 'frame':\n return driver.invokeReflex(driver.frame, payload)\n case 'window':\n return driver.invokeReflex(payload)\n }\n } catch (error) {\n lifecycle.dispatch(lifecycle.events.clientError, element, {\n error,\n ...payload\n })\n }\n}\n\n// wire things up and setup defaults for event delegation\ndelegates.handler = invokeReflex\ndelegates.register('change', [\n `input[${schema.reflexAttribute}]`,\n `select[${schema.reflexAttribute}]`,\n `textarea[${schema.reflexAttribute}]`\n])\n// delegates.register('mousedown', [\n// `[${schema.reflexAttribute}][${schema.methodAttribute}]`\n// ])\ndelegates.register('submit', [`form[${schema.reflexAttribute}]`])\ndelegates.register('click', [`[${schema.reflexAttribute}]`])\n\nexport default {\n schema,\n logger,\n registerEventDelegate: delegates.register,\n get eventDelegates () {\n return { ...delegates.events }\n },\n get lifecycleEvents () {\n return [...Object.values(lifecycle.events)]\n }\n}\n"],
5
- "mappings": "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",
6
- "names": ["Meta", "value", "meta_default", "replaceDocument", "content", "head", "tail", "headIndex", "tailIndex", "html", "append", "renderer_default", "active", "add", "payload", "remove", "id", "activity_default", "events", "dispatch", "name", "target", "detail", "raise", "event", "error", "dispatchClientError", "finish", "activity_default", "lifecycle_default", "frameSources", "event", "frame", "fetchOptions", "meta_default", "acceptHeaders", "entry", "chunk", "i", "response", "error", "lifecycle_default", "content", "renderer_default", "schema", "schema_default", "events", "eventListener", "register", "eventName", "selectors", "getRegisteredEventNameForElement", "element", "selector", "el", "isRegisteredForElement", "delegates_default", "fn", "findClosestReflex", "element", "schema_default", "findClosestFrame", "assignElementValueToPayload", "payload", "memo", "option", "buildAttributePayload", "attr", "value", "elements_default", "invokeReflex", "form", "payload", "meta_default", "input", "form_default", "build", "urlString", "payload", "a", "url", "urls_default", "invokeReflex", "frame", "payload", "src", "urls_default", "frame_default", "invokeReflex", "element", "payload", "src", "urls_default", "method_default", "aborted", "event", "xhr", "lifecycle_default", "errored", "renderer_default", "error", "loaded", "content", "invokeReflex", "payload", "src", "urls_default", "meta_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", "lifecycle_default", "name", "event", "logger_default", "value", "v4", "c", "uuids_default", "invokeReflex", "event", "element", "payload", "elements_default", "delegates_default", "driver", "drivers_default", "uuids_default", "activity_default", "lifecycle_default", "meta_default", "error", "schema_default", "javascript_default", "logger_default"]
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/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-reflex\"]')\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 lifecycleEvents = {\n start: 'turbo-reflex:start',\n success: 'turbo-reflex:success',\n finish: 'turbo-reflex:finish',\n abort: 'turbo-reflex:abort',\n clientError: 'turbo-reflex:client-error',\n serverError: 'turbo-reflex:server-error'\n}\n\nexport const stateEvents = {\n beforeStateChange: 'turbo-reflex:before-state-change',\n stateChange: 'turbo-reflex:state-change'\n}\n\nexport const allEvents = { ...lifecycleEvents, ...stateEvents }\n\nexport function dispatch (name, target = document, detail = {}, raise = false) {\n try {\n target = target || document\n const event = new CustomEvent(name, {\n detail,\n cancelable: false,\n bubbles: true\n })\n target.dispatchEvent(event)\n } catch (error) {\n if (raise) throw error\n dispatch(lifecycleEvents.clientError, target, { error, ...detail }, true)\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 dispatch(events.beforeStateChange, meta.element, { state: head })\n delete target[key]\n dispatch(events.stateChange, meta.element, { state: head })\n return true\n },\n\n set (target, key, value, receiver) {\n dispatch(events.beforeStateChange, meta.element, { state: head })\n target[key] = observable(value, this)\n dispatch(events.stateChange, meta.element, { 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))\n 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 { stateEvents as events } from '../events'\n\nlet oldState, state, changedState\nlet observer\n\nfunction loadState () {\n const json = atob(meta.element.dataset.state)\n changedState = {}\n oldState = state = observable(JSON.parse(json))\n}\n\nfunction initObserver () {\n if (observer) observer.disconnect()\n observer = new MutationObserver(loadState)\n observer.observe(meta.element, {\n attributes: true,\n attributeFilter: ['data-state']\n })\n}\n\naddEventListener('DOMContentLoaded', loadState)\naddEventListener('DOMContentLoaded', initObserver)\naddEventListener('turbo:load', initObserver)\naddEventListener('turbo:frame-load', initObserver)\n\naddEventListener(\n events.beforeStateChange,\n event => (oldState = JSON.parse(JSON.stringify(state)))\n)\n\naddEventListener(events.stateChange, event => {\n changedState = {}\n for (const [key, value] of Object.entries(state))\n if (oldState[key] !== value) changedState[key] = value\n meta.element.dataset.state = btoa(JSON.stringify(state))\n})\n\nexport { state }\nexport default {\n events,\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 reflexes () {\n return [...Object.values(active)]\n },\n get length () {\n return Object.keys(active).length\n }\n}\n", "import activity from './activity'\nimport { dispatch, lifecycleEvents as events } from './events'\n\nfunction finish (event) {\n event.detail.endedAt = new Date().getTime()\n event.detail.milliseconds = event.detail.endedAt - event.detail.startedAt\n setTimeout(() => dispatch(events.finish, event.target, event.detail), 20)\n}\n\naddEventListener(events.serverError, finish)\naddEventListener(events.success, finish)\naddEventListener(events.finish, event => activity.remove(event.detail.id), true)\n\nexport default { events }\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 // reflex invoked and busy\n if (meta.busy) {\n let acceptHeaders = [\n 'text/vnd.turbo-reflex.html',\n fetchOptions.headers['Accept']\n ]\n acceptHeaders = acceptHeaders\n .filter(entry => entry && entry.trim().length > 0)\n .join(', ')\n fetchOptions.headers['Accept'] = acceptHeaders\n fetchOptions.headers['TurboReflex-Token'] = meta.token\n }\n\n // always send state\n state.payloadChunks.forEach(\n (chunk, i) =>\n (fetchOptions.headers[\n `TurboReflex-State-${i.toString().padStart(4, '0')}`\n ] = 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('TurboReflex')) {\n if (response.statusCode < 200 || response.statusCode > 399) {\n const error = `Server returned a ${response.statusCode} status code! TurboReflex requires 2XX-3XX status codes.`\n dispatch(\n lifecycle.events.clientError,\n document,\n { ...event.detail, error },\n true\n )\n }\n\n if (response.header('TurboReflex') === '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.turboReflexSrc =\n frameSources[frame.id] || frame.src || frame.dataset.turboReflexSrc\n delete frameSources[frame.id]\n})\n", "const schema = {\n frameAttribute: 'data-turbo-frame',\n methodAttribute: 'data-turbo-method',\n reflexAttribute: 'data-turbo-reflex'\n}\n\nexport default { ...schema }\n", "const events = {}\nlet eventListener\n\nfunction register (eventName, selectors) {\n events[eventName] = selectors\n document.addEventListener(eventName, eventListener, true)\n}\n\nfunction getRegisteredEventNameForElement (element) {\n return Object.keys(events).find(eventName => {\n return !!events[eventName].find(selector =>\n Array.from(document.querySelectorAll(selector)).find(el => el === element)\n )\n })\n}\n\nfunction isRegisteredForElement (eventName, element) {\n return eventName === getRegisteredEventNameForElement(element)\n}\n\nexport default {\n events,\n register,\n isRegisteredForElement,\n set handler (fn) {\n eventListener = fn\n }\n}\n", "import schema from './schema'\nimport lifecycle from './lifecycle'\n\nfunction findClosestReflex (element) {\n return element.closest(`[${schema.reflexAttribute}]`)\n}\n\nfunction findClosestFrame (element) {\n return element.closest('turbo-frame')\n}\n\nfunction assignElementValueToPayload (element, payload = {}) {\n if (element.tagName.toLowerCase() !== 'select')\n return (payload.value = element.value || null)\n\n if (!element.multiple)\n 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.reflexAttribute]\n delete payload[schema.frameAttribute]\n\n return payload\n}\n\nexport default {\n buildAttributePayload,\n findClosestReflex,\n findClosestFrame\n}\n", "import meta from '../meta'\n\nfunction invokeReflex (form, payload = {}) {\n payload.token = meta.token\n const input = document.createElement('input')\n input.type = 'hidden'\n input.name = 'turbo_reflex'\n input.value = JSON.stringify(payload)\n form.appendChild(input)\n}\n\nexport default { invokeReflex }\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_reflex', JSON.stringify(payload))\n return url\n}\n\nexport default { build }\n", "import urls from '../urls'\n\nfunction invokeReflex (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 { invokeReflex }\n", "import urls from '../urls'\n\nfunction invokeReflex (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 { invokeReflex }\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, { xhr, ...event.detail })\n}\n\nfunction errored (event) {\n const xhr = event.target\n\n xhr.getResponseHeader('TurboReflex') === 'Append'\n ? renderer.append(xhr.responseText)\n : renderer.replaceDocument(xhr.responseText)\n\n const error = `Server returned a ${xhr.status} status code! TurboReflex requires 2XX-3XX status codes.`\n\n dispatch(\n lifecycle.events.clientError,\n document,\n { xhr, ...event.detail, error },\n true\n )\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 xhr.getResponseHeader('TurboReflex') === 'Append'\n ? renderer.append(xhr.responseText)\n : renderer.replaceDocument(xhr.responseText)\n}\n\nfunction invokeReflex (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(\n 'Accept',\n 'text/vnd.turbo-reflex.html, text/html, application/xhtml+xml'\n )\n xhr.setRequestHeader('TurboReflex-Token', meta.token)\n state.payloadChunks.forEach((chunk, i) =>\n xhr.setRequestHeader(\n `TurboReflex-State-${i.toString().padStart(4, '0')}`,\n chunk\n )\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 { invokeReflex }\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 (\n element.href || frame.src || frame.dataset.turboReflexSrc || location.href\n )\n}\n\nfunction find (element) {\n let frame = elements.findClosestFrame(element)\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 invokeReflex: formDriver.invokeReflex\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 invokeReflex: methodDriver.invokeReflex\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 invokeReflex: frameDriver.invokeReflex\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:\n 'element does NOT target a frame or targets _self and is contained by a frame',\n frame,\n src: src(element, frame),\n invokeReflex: frameDriver.invokeReflex\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 invokeReflex: windowDriver.invokeReflex\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 level = currentLevel === 'debug' ? 'log' : currentLevel\n console[level](event.type, event.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 (\n c ^\n (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (c / 4)))\n ).toString(16)\n )\n}\n\nexport default { v4 }\n", "import './turbo'\nimport schema from './schema'\nimport { dispatch } from './events'\nimport activity from './activity'\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 invokeReflex (event) {\n let element\n let payload = {}\n\n try {\n element = elements.findClosestReflex(event.target)\n if (!element) return\n if (!delegates.isRegisteredForElement(event.type, element)) return\n\n const driver = drivers.find(element)\n\n // payload sent to server (also used for lifecycle event.detail)\n payload = {\n id: `reflex-${uuids.v4()}`,\n name: element.dataset.turboReflex,\n driver: driver.name,\n src: driver.src,\n frameId: driver.frame ? driver.frame.id : null,\n elementId: element.id.length > 0 ? element.id : null,\n elementAttributes: elements.buildAttributePayload(element),\n startedAt: new Date().getTime()\n }\n\n activity.add(payload)\n dispatch(lifecycle.events.start, element, 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.invokeReflex(element, payload)\n case 'form':\n return driver.invokeReflex(element, payload)\n case 'frame':\n return driver.invokeReflex(driver.frame, payload)\n case 'window':\n return driver.invokeReflex(payload)\n }\n } catch (error) {\n dispatch(lifecycle.events.clientError, element, {\n error,\n ...payload\n })\n }\n}\n\n// wire things up and setup defaults for event delegation\ndelegates.handler = invokeReflex\ndelegates.register('change', [\n `input[${schema.reflexAttribute}]`,\n `select[${schema.reflexAttribute}]`,\n `textarea[${schema.reflexAttribute}]`\n])\n// delegates.register('mousedown', [\n// `[${schema.reflexAttribute}][${schema.methodAttribute}]`\n// ])\ndelegates.register('submit', [`form[${schema.reflexAttribute}]`])\ndelegates.register('click', [`[${schema.reflexAttribute}]`])\n\nexport default self.TurboReflex = {\n logger,\n schema,\n registerEventDelegate: delegates.register,\n get eventDelegates () {\n return { ...delegates.events }\n },\n get lifecycleEvents () {\n return [...Object.values(lifecycle.events)]\n },\n get state () {\n return state\n }\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["Meta", "value", "meta_default", "lifecycleEvents", "stateEvents", "allEvents", "dispatch", "name", "target", "detail", "raise", "event", "error", "head", "observable", "object", "parent", "proxy", "target", "key", "dispatch", "stateEvents", "meta_default", "value", "receiver", "index", "observable_default", "oldState", "state", "changedState", "observer", "loadState", "json", "meta_default", "observable_default", "initObserver", "stateEvents", "event", "key", "value", "state_default", "stateEvents", "changedState", "replaceDocument", "content", "head", "tail", "headIndex", "tailIndex", "html", "append", "renderer_default", "active", "add", "payload", "remove", "id", "activity_default", "finish", "event", "dispatch", "lifecycleEvents", "activity_default", "lifecycle_default", "frameSources", "event", "frame", "fetchOptions", "meta_default", "acceptHeaders", "entry", "state_default", "chunk", "i", "response", "error", "dispatch", "lifecycle_default", "content", "renderer_default", "schema", "schema_default", "events", "eventListener", "register", "eventName", "selectors", "getRegisteredEventNameForElement", "element", "selector", "el", "isRegisteredForElement", "delegates_default", "fn", "findClosestReflex", "element", "schema_default", "findClosestFrame", "assignElementValueToPayload", "payload", "memo", "option", "buildAttributePayload", "attr", "value", "elements_default", "invokeReflex", "form", "payload", "meta_default", "input", "form_default", "build", "urlString", "payload", "a", "url", "urls_default", "invokeReflex", "frame", "payload", "src", "urls_default", "frame_default", "invokeReflex", "element", "payload", "src", "urls_default", "method_default", "aborted", "event", "xhr", "dispatch", "lifecycle_default", "errored", "renderer_default", "error", "loaded", "content", "invokeReflex", "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", "logger_default", "value", "v4", "c", "uuids_default", "invokeReflex", "event", "element", "payload", "elements_default", "delegates_default", "driver", "drivers_default", "uuids_default", "activity_default", "dispatch", "lifecycle_default", "meta_default", "error", "schema_default", "javascript_default", "logger_default", "state"]
7
7
  }
@@ -3,6 +3,20 @@
3
3
  module TurboReflex::Controller
4
4
  extend ActiveSupport::Concern
5
5
 
6
+ module ClassMethods
7
+ def turbo_reflex_state_cookie_max_bytesize
8
+ TurboReflex::StateManager.cookie_max_bytesize
9
+ end
10
+
11
+ def turbo_reflex_state_cookie_max_bytesize=(value)
12
+ TurboReflex::StateManager.cookie_max_bytesize = value
13
+ end
14
+
15
+ def turbo_reflex_state(&block)
16
+ TurboReflex::StateManager.add_state_override_block name, block
17
+ end
18
+ end
19
+
6
20
  included do
7
21
  before_action -> { turbo_reflex.run }
8
22
  after_action -> { turbo_reflex.update_response }
@@ -1,11 +1,13 @@
1
1
  import meta from '../meta'
2
+ import state from '../state'
3
+ import { dispatch } from '../events'
2
4
  import lifecycle from '../lifecycle'
3
5
  import urls from '../urls'
4
6
  import renderer from '../renderer'
5
7
 
6
8
  function aborted (event) {
7
9
  const xhr = event.target
8
- lifecycle.dispatch(lifecycle.events.abort, window, { xhr, ...event.detail })
10
+ dispatch(lifecycle.events.abort, document, { xhr, ...event.detail })
9
11
  }
10
12
 
11
13
  function errored (event) {
@@ -16,7 +18,13 @@ function errored (event) {
16
18
  : renderer.replaceDocument(xhr.responseText)
17
19
 
18
20
  const error = `Server returned a ${xhr.status} status code! TurboReflex requires 2XX-3XX status codes.`
19
- lifecycle.dispatchClientError({ xhr, ...event.detail, error })
21
+
22
+ dispatch(
23
+ lifecycle.events.clientError,
24
+ document,
25
+ { xhr, ...event.detail, error },
26
+ true
27
+ )
20
28
  }
21
29
 
22
30
  function loaded (event) {
@@ -41,9 +49,9 @@ function invokeReflex (payload) {
41
49
  'text/vnd.turbo-reflex.html, text/html, application/xhtml+xml'
42
50
  )
43
51
  xhr.setRequestHeader('TurboReflex-Token', meta.token)
44
- meta.uiStateBase64Chunks.forEach((chunk, i) =>
52
+ state.payloadChunks.forEach((chunk, i) =>
45
53
  xhr.setRequestHeader(
46
- `TurboReflex-UiState-${i.toString().padStart(6, '0')}`,
54
+ `TurboReflex-State-${i.toString().padStart(4, '0')}`,
47
55
  chunk
48
56
  )
49
57
  )
@@ -1,4 +1,4 @@
1
- import schema from './schema.js'
1
+ import schema from './schema'
2
2
  import lifecycle from './lifecycle'
3
3
 
4
4
  function findClosestReflex (element) {
@@ -0,0 +1,30 @@
1
+ export const lifecycleEvents = {
2
+ start: 'turbo-reflex:start',
3
+ success: 'turbo-reflex:success',
4
+ finish: 'turbo-reflex:finish',
5
+ abort: 'turbo-reflex:abort',
6
+ clientError: 'turbo-reflex:client-error',
7
+ serverError: 'turbo-reflex:server-error'
8
+ }
9
+
10
+ export const stateEvents = {
11
+ beforeStateChange: 'turbo-reflex:before-state-change',
12
+ stateChange: 'turbo-reflex:state-change'
13
+ }
14
+
15
+ export const allEvents = { ...lifecycleEvents, ...stateEvents }
16
+
17
+ export function dispatch (name, target = document, detail = {}, raise = false) {
18
+ try {
19
+ target = target || document
20
+ const event = new CustomEvent(name, {
21
+ detail,
22
+ cancelable: false,
23
+ bubbles: true
24
+ })
25
+ target.dispatchEvent(event)
26
+ } catch (error) {
27
+ if (raise) throw error
28
+ dispatch(lifecycleEvents.clientError, target, { error, ...detail }, true)
29
+ }
30
+ }
@@ -1,5 +1,6 @@
1
1
  import './turbo'
2
- import schema from './schema.js'
2
+ import schema from './schema'
3
+ import { dispatch } from './events'
3
4
  import activity from './activity'
4
5
  import delegates from './delegates'
5
6
  import drivers from './drivers'
@@ -7,6 +8,7 @@ import meta from './meta'
7
8
  import elements from './elements'
8
9
  import lifecycle from './lifecycle'
9
10
  import logger from './logger'
11
+ import { state } from './state'
10
12
  import urls from './urls'
11
13
  import uuids from './uuids'
12
14
 
@@ -34,7 +36,7 @@ function invokeReflex (event) {
34
36
  }
35
37
 
36
38
  activity.add(payload)
37
- lifecycle.dispatch(lifecycle.events.start, element, payload)
39
+ dispatch(lifecycle.events.start, element, payload)
38
40
 
39
41
  if (['frame', 'window'].includes(driver.name)) event.preventDefault()
40
42
 
@@ -52,7 +54,7 @@ function invokeReflex (event) {
52
54
  return driver.invokeReflex(payload)
53
55
  }
54
56
  } catch (error) {
55
- lifecycle.dispatch(lifecycle.events.clientError, element, {
57
+ dispatch(lifecycle.events.clientError, element, {
56
58
  error,
57
59
  ...payload
58
60
  })
@@ -72,14 +74,17 @@ delegates.register('change', [
72
74
  delegates.register('submit', [`form[${schema.reflexAttribute}]`])
73
75
  delegates.register('click', [`[${schema.reflexAttribute}]`])
74
76
 
75
- export default {
76
- schema,
77
+ export default self.TurboReflex = {
77
78
  logger,
79
+ schema,
78
80
  registerEventDelegate: delegates.register,
79
81
  get eventDelegates () {
80
82
  return { ...delegates.events }
81
83
  },
82
84
  get lifecycleEvents () {
83
85
  return [...Object.values(lifecycle.events)]
86
+ },
87
+ get state () {
88
+ return state
84
89
  }
85
90
  }
@@ -1,32 +1,5 @@
1
1
  import activity from './activity'
2
-
3
- const events = {
4
- start: 'turbo-reflex:start',
5
- success: 'turbo-reflex:success',
6
- finish: 'turbo-reflex:finish',
7
- abort: 'turbo-reflex:abort',
8
- clientError: 'turbo-reflex:client-error',
9
- serverError: 'turbo-reflex:server-error'
10
- }
11
-
12
- function dispatch (name, target = document, detail = {}, raise = false) {
13
- try {
14
- target = target || document
15
- const event = new CustomEvent(name, {
16
- detail,
17
- cancelable: false,
18
- bubbles: true
19
- })
20
- target.dispatchEvent(event)
21
- } catch (error) {
22
- if (raise) throw error
23
- dispatch(events.clientError, target, { error, ...detail }, true)
24
- }
25
- }
26
-
27
- function dispatchClientError (detail = {}) {
28
- dispatch(events.clientError, window, detail, true)
29
- }
2
+ import { dispatch, lifecycleEvents as events } from './events'
30
3
 
31
4
  function finish (event) {
32
5
  event.detail.endedAt = new Date().getTime()
@@ -38,8 +11,4 @@ addEventListener(events.serverError, finish)
38
11
  addEventListener(events.success, finish)
39
12
  addEventListener(events.finish, event => activity.remove(event.detail.id), true)
40
13
 
41
- export default {
42
- dispatch,
43
- dispatchClientError,
44
- events
45
- }
14
+ export default { events }
@@ -1,20 +1,16 @@
1
- import lifecycle from './lifecycle'
1
+ import { allEvents as events } from './events'
2
2
 
3
3
  let currentLevel = 'unknown'
4
4
 
5
5
  const logLevels = {
6
- debug: Object.values(lifecycle.events),
7
- info: Object.values(lifecycle.events),
8
- warn: [
9
- lifecycle.events.abort,
10
- lifecycle.events.clientError,
11
- lifecycle.events.serverError
12
- ],
13
- error: [lifecycle.events.clientError, lifecycle.events.serverError],
6
+ debug: Object.values(events),
7
+ info: Object.values(events),
8
+ warn: [events.abort, events.clientError, events.serverError],
9
+ error: [events.clientError, events.serverError],
14
10
  unknown: []
15
11
  }
16
12
 
17
- Object.values(lifecycle.events).forEach(name => {
13
+ Object.values(events).forEach(name => {
18
14
  addEventListener(name, event => {
19
15
  if (logLevels[currentLevel].includes(event.type)) {
20
16
  const level = currentLevel === 'debug' ? 'log' : currentLevel
@@ -14,27 +14,6 @@ class Meta {
14
14
  set busy (value) {
15
15
  return (this.element.dataset.busy = !!value)
16
16
  }
17
-
18
- get uiStateBase64 () {
19
- return this.element.dataset.uiState
20
- }
21
-
22
- // UI state gets split into chunks and sent to the server in an HTTP request header.
23
- // Max size for an HTTP header is around 4k or 4,000 bytes.
24
- // A Base64 character is an 8-bit-padded ASCII character... or 1 byte
25
- //
26
- // SEE: lib/ui_state.rb - for info on how UiState is serialized/deserialized
27
- get uiStateBase64Chunks () {
28
- return this.uiStateBase64.match(/.{1,2000}/g)
29
- }
30
-
31
- get uiStateJSON () {
32
- return atob(this.uiStateBase64)
33
- }
34
-
35
- get uiState () {
36
- return JSON.parse(this.uiStateJSON)
37
- }
38
17
  }
39
18
 
40
19
  export default new Meta()
@@ -0,0 +1,52 @@
1
+ import meta from '../meta'
2
+ import observable from './observable'
3
+ import { stateEvents as events } from '../events'
4
+
5
+ let oldState, state, changedState
6
+ let observer
7
+
8
+ function loadState () {
9
+ const json = atob(meta.element.dataset.state)
10
+ changedState = {}
11
+ oldState = state = observable(JSON.parse(json))
12
+ }
13
+
14
+ function initObserver () {
15
+ if (observer) observer.disconnect()
16
+ observer = new MutationObserver(loadState)
17
+ observer.observe(meta.element, {
18
+ attributes: true,
19
+ attributeFilter: ['data-state']
20
+ })
21
+ }
22
+
23
+ addEventListener('DOMContentLoaded', loadState)
24
+ addEventListener('DOMContentLoaded', initObserver)
25
+ addEventListener('turbo:load', initObserver)
26
+ addEventListener('turbo:frame-load', initObserver)
27
+
28
+ addEventListener(
29
+ events.beforeStateChange,
30
+ event => (oldState = JSON.parse(JSON.stringify(state)))
31
+ )
32
+
33
+ addEventListener(events.stateChange, event => {
34
+ changedState = {}
35
+ for (const [key, value] of Object.entries(state))
36
+ if (oldState[key] !== value) changedState[key] = value
37
+ meta.element.dataset.state = btoa(JSON.stringify(state))
38
+ })
39
+
40
+ export { state }
41
+ export default {
42
+ events,
43
+
44
+ // The UI state changes are split into chunks and sent to the server in an HTTP request header.
45
+ // Max size for an HTTP header is around 4k or 4,000 bytes.
46
+ // A Base64 character is an 8-bit-padded ASCII character... or 1 byte
47
+ //
48
+ // SEE: lib/state.rb - for info on how `state` is serialized/deserialized
49
+ get payloadChunks () {
50
+ return btoa(JSON.stringify(changedState)).match(/.{1,2000}/g)
51
+ }
52
+ }