overlastic 0.6.1 → 0.7.0

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: a7eea3ffc551ed8da8f0f8946e5e5d29a8617579eb6519ac50607f3dc95359a5
4
- data.tar.gz: cd7b37ef5289b3d1243a8e75ac59782d639a00b33b33f04d46c6d422eff0994b
3
+ metadata.gz: d3ab674f782fbcf5b2a76e0aa8e4d229b87101318c37aba073ce60c648ec3d22
4
+ data.tar.gz: a61d7ae32a857901b42d2f06c31e04ed16e51d6cf1d79a6e22e8339f5aa64300
5
5
  SHA512:
6
- metadata.gz: f3a60109a2f9cb74a687c0d8b9a3c74f0ca6bd65c66c73aa22214c349acc7dfbb337e69c7438696dd8dd9ba127c3095ecdf024be66b7123daf3ee369e8581eb9
7
- data.tar.gz: b8c610c362f001a74a4dd00bcd78a6df7a2fe005451f41423ad619bda71dd7dc7734109b75c1a0547d298f27c656efe9f3647c6858ed5e26ceeb39ec804d29b8
6
+ metadata.gz: f1bd556df73b2f2f3334bf49f6c4925ac7cf436b1b5556931e5aa80033785b15e9a77131383963beb2e91f0073a02f3612e62cbd29000e3667be19640fcf58c2
7
+ data.tar.gz: dcb9b6a055883ef195d9c393a30d8e34bbd8f5f51a41f43e52d8c9fc56130971814442e223d991ee5895b36df20b00ebfc55af2c55e809ac9bc15d671da37c4d
data/README.md CHANGED
@@ -35,8 +35,8 @@ They work just as `link_to` and accept the same options. You can also pass local
35
35
  Nested overlays will stack on top of each other. You can instead replace the last one or the whole stack:
36
36
 
37
37
  ```erb
38
- <%= link_to_dialog "Open dialog", edit_article_path, overlay_action: :replace_last %>
39
- <%= link_to_dialog "Open dialog", edit_article_path, overlay_action: :replace_all %>
38
+ <%= link_to_dialog "Open dialog", edit_article_path, overlay: :last %>
39
+ <%= link_to_dialog "Open dialog", edit_article_path, overlay: :first %>
40
40
  ```
41
41
 
42
42
  By default, links and forms inside an overlay will drive the entire page (target _top). To keep navigation within the overlay you can set its target to _self:
@@ -45,6 +45,12 @@ By default, links and forms inside an overlay will drive the entire page (target
45
45
  <%= link_to_dialog "Open dialog", edit_article_path, overlay_target: :_self %>
46
46
  ```
47
47
 
48
+ To break out of an overlay with target _self you can use:
49
+
50
+ ```erb
51
+ <%= link_to "Open whole page", edit_article_path, overlay: false %>
52
+ ```
53
+
48
54
  A common use case is to render a form inside an overlay. When the form is submitted, you'll validate the data and redirect to a different page if it's successful or render the form again with errors. Overlastic will handle both cases gracefully without any modifications:
49
55
 
50
56
  ```rb
@@ -61,12 +67,13 @@ In case the form overlay was nested inside another overlay, you could prefer to
61
67
  redirect_to article_url(@article), overlay: :previous, status: :see_other
62
68
  ```
63
69
 
64
- Sometimes, you may want to alter the content of a view depending on whether it's inside an overlay or not. Overlastic defines a new `:overlay` request variant that you can use to create custom partials like `_form.html+overlay.erb` or inside a controller like so:
70
+ Sometimes, you may want to alter the content of a view depending on whether it's inside an overlay or not. Overlastic defines a new `:overlay` request variant that you can use to create custom views like `new.html+overlay.erb` or inside a controller like so:
65
71
 
66
72
  ```rb
67
73
  respond_to do |format|
68
- format.html.overlay { render :custom_view }
69
- format.html.any
74
+ format.turbo_stream.overlay { render :custom_view }
75
+ format.turbo_stream.any
76
+ format.html
70
77
  end
71
78
  ```
72
79
 
@@ -83,8 +90,10 @@ else
83
90
  end
84
91
  ```
85
92
 
93
+ ### Advanced features
94
+
86
95
  <details>
87
- <summary>Advanced: Rendering an overlay without an initiator</summary><br>
96
+ <summary>Rendering an overlay without an initiator</summary><br>
88
97
 
89
98
  Overlastic extends the `render` method inside a controller to add all the same options as `link_to_overlay`. This allows you to force an action to render an overlay, even if it wasn't requested:
90
99
 
@@ -94,6 +103,43 @@ end
94
103
  ```
95
104
  </details>
96
105
 
106
+ <details>
107
+ <summary>Appending Turbo Streams to close_overlay</summary><br>
108
+
109
+ Sometimes, you may want not only to close an overlay, but also to deliver some other page change using a Turbo Stream:
110
+
111
+ ```rb
112
+ close_overlay do
113
+ turbo_stream.prepend("flash-messages", "Deleted!")
114
+ end
115
+ ```
116
+ </details>
117
+
118
+ <details>
119
+ <summary>Appending Turbo Streams to every response</summary><br>
120
+
121
+ Overlastic can be configured to append a Turbo Stream to every response that contains an overlay.
122
+ This can be very useful for rendering flash messages:
123
+
124
+ ```rb
125
+ Overlastic.configure do |config|
126
+ config.append_turbo_stream do
127
+ turbo_stream.replace("flash-messages", partial: "shared/flash_messages")
128
+ end
129
+ end
130
+ ```
131
+
132
+ Then you'd only need to specify a flash message when closing an overlay, or redirecting to a different path:
133
+
134
+ ```rb
135
+ close_overlay notice: "Deleted!"
136
+
137
+ # or
138
+
139
+ redirect_to articles_path, notice: "Deleted!", status: :see_other
140
+ ```
141
+ </details>
142
+
97
143
 
98
144
  ## Configuration
99
145
 
@@ -102,13 +148,18 @@ end
102
148
 
103
149
  Overlastic.configure do |config|
104
150
  config.overlay_types = %i[dialog pane]
105
- config.default_overlay = :dialog
106
- config.default_action = :stack
107
- config.default_target = :_top
151
+ config.default_overlay = :dialog # Options: One of the defined overlay types
152
+ config.default_action = :stack # Options: :stack, :replace_last, :replace_all
153
+ config.default_target = :_top # Options: :_top, :_self
108
154
 
109
155
  # You can define a custom partial for each overlay type
110
156
  config.dialog_overlay_view_path = "overlays/dialog"
111
157
  config.pane_overlay_view_path = "overlays/pane"
158
+
159
+ # You can append Turbo Streams to every response containing an overlay
160
+ config.append_turbo_stream do
161
+ turbo_stream.replace("flash-messages", partial: "shared/flash_messages")
162
+ end
112
163
  end
113
164
  ```
114
165
 
@@ -139,12 +190,6 @@ Overlastic comes with default views for both the dialog and pane overlays. It al
139
190
 
140
191
  ## Development
141
192
 
142
- <details>
143
- <summary>Roadmap</summary><br>
144
-
145
- - Toasts?
146
- </details>
147
-
148
193
  <details>
149
194
  <summary>Running the demo application</summary><br>
150
195
 
@@ -203,13 +203,7 @@ var enableBodyScroll$1 = function enableBodyScroll(targetElement) {
203
203
  };
204
204
 
205
205
  addEventListener("click", (event => {
206
- window._overlasticAnchor = event.target.closest("a[data-turbo-frame^=overlay]");
207
- }), true);
208
-
209
- addEventListener("turbo:before-fetch-request", (event => {
210
- if (!event.target.hasAttribute("cancel")) return;
211
- event.preventDefault();
212
- event.target.removeAttribute("cancel");
206
+ window._overlasticAnchor = event.target;
213
207
  }), true);
214
208
 
215
209
  addEventListener("turbo:before-fetch-request", (event => {
@@ -217,32 +211,58 @@ addEventListener("turbo:before-fetch-request", (event => {
217
211
  }));
218
212
 
219
213
  addEventListener("turbo:before-fetch-request", (event => {
220
- if (!window._overlasticAnchor) return;
221
- const anchor = window._overlasticAnchor;
214
+ const anchor = event.target;
215
+ const name = anchor?.dataset?.overlayName;
222
216
  const type = anchor?.dataset?.overlayType;
223
217
  const target = anchor?.dataset?.overlayTarget;
224
218
  const args = anchor?.dataset?.overlayArgs;
225
- event.detail.fetchOptions.headers["Overlay-Initiator"] = "1";
226
- if (type) {
227
- event.detail.fetchOptions.headers["Overlay-Type"] = type;
228
- }
229
- if (target) {
230
- event.detail.fetchOptions.headers["Overlay-Target"] = target;
219
+ if (name?.startsWith("overlay")) {
220
+ event.detail.fetchOptions.headers["Overlay-Initiator"] = "1";
221
+ event.detail.fetchOptions.headers["Overlay-Name"] = name;
222
+ if (type) {
223
+ event.detail.fetchOptions.headers["Overlay-Type"] = type;
224
+ }
225
+ if (target) {
226
+ event.detail.fetchOptions.headers["Overlay-Target"] = target;
227
+ }
228
+ if (args) {
229
+ event.detail.fetchOptions.headers["Overlay-Args"] = args;
230
+ }
231
231
  }
232
- if (args) {
233
- event.detail.fetchOptions.headers["Overlay-Args"] = args;
232
+ }));
233
+
234
+ addEventListener("turbo:before-fetch-request", (event => {
235
+ const script = document.querySelector("script[overlay]");
236
+ if (script) {
237
+ const overlay = document.querySelector(`overlastic[id=${script.getAttribute("overlay")}]`);
238
+ if (overlay) {
239
+ const name = overlay.id;
240
+ const target = overlay.dataset.overlayTarget;
241
+ const type = overlay.dataset?.overlayType;
242
+ const args = overlay.dataset?.overlayArgs;
243
+ event.detail.fetchOptions.headers["Overlay-Name"] = name;
244
+ event.detail.fetchOptions.headers["Overlay-Target"] = target;
245
+ event.detail.fetchOptions.headers["Overlay-Initiator"] = "1";
246
+ if (type) {
247
+ event.detail.fetchOptions.headers["Overlay-Type"] = type;
248
+ }
249
+ if (args) {
250
+ event.detail.fetchOptions.headers["Overlay-Args"] = args;
251
+ }
252
+ }
234
253
  }
235
- delete window._overlasticTarget;
236
254
  }));
237
255
 
238
256
  addEventListener("turbo:before-fetch-request", (event => {
239
- if (window._overlasticAnchor) return;
240
- const frame = event.target.closest("turbo-frame[id^=overlay]");
241
- if (frame) {
242
- const target = frame.dataset.overlayTarget;
243
- const initiator = frame.dataset?.overlayInitiator;
244
- const type = frame.dataset?.overlayType;
245
- const args = frame.dataset?.overlayArgs;
257
+ const anchor = window._overlasticAnchor;
258
+ const overlay = anchor.closest("overlastic");
259
+ if (overlay && !anchor.dataset.overlay && !anchor.dataset.overlayName) {
260
+ const name = overlay.id;
261
+ const target = overlay.dataset.overlayTarget;
262
+ const initiator = overlay.dataset?.overlayInitiator;
263
+ const type = overlay.dataset?.overlayType;
264
+ const args = overlay.dataset?.overlayArgs;
265
+ event.detail.fetchOptions.headers["Overlay-Name"] = name;
246
266
  event.detail.fetchOptions.headers["Overlay-Target"] = target;
247
267
  if (initiator) {
248
268
  event.detail.fetchOptions.headers["Overlay-Initiator"] = initiator;
@@ -254,22 +274,7 @@ addEventListener("turbo:before-fetch-request", (event => {
254
274
  event.detail.fetchOptions.headers["Overlay-Args"] = args;
255
275
  }
256
276
  }
257
- }));
258
-
259
- addEventListener("turbo:before-fetch-response", (async event => {
260
- const fetchResponse = event.detail.fetchResponse;
261
- const visit = fetchResponse.response.headers.get("Overlay-Visit");
262
- if (!visit) return;
263
- const responseHTML = await fetchResponse.responseHTML;
264
- const {redirected: redirected, statusCode: statusCode} = fetchResponse;
265
- return Turbo.session.visit(visit, {
266
- shouldCacheSnapshot: false,
267
- response: {
268
- redirected: redirected,
269
- statusCode: statusCode,
270
- responseHTML: responseHTML
271
- }
272
- });
277
+ delete window._overlasticAnchor;
273
278
  }));
274
279
 
275
280
  class DialogElement extends HTMLElement {
@@ -297,7 +302,7 @@ class PaneElement extends DialogElement {
297
302
  window.modalVisitStack = [];
298
303
  }
299
304
  window.modalVisitStack.push(lastVisit);
300
- Turbo.navigator.history.push(new URL(this.parentElement.src));
305
+ Turbo.navigator.history.push(new URL(this.parentElement.getAttribute("src")));
301
306
  }
302
307
  close(event, self = false) {
303
308
  if (self && event.target !== this) return;
@@ -1,2 +1,2 @@
1
- var e=!1;if("undefined"!=typeof window){var t={get passive(){e=!0}};window.addEventListener("testPassive",null,t),window.removeEventListener("testPassive",null,t)}var o="undefined"!=typeof window&&window.navigator&&window.navigator.platform&&(/iP(ad|hone|od)/.test(window.navigator.platform)||"MacIntel"===window.navigator.platform&&window.navigator.maxTouchPoints>1),n=[],r=!1,i=-1,a=void 0,s=void 0,d=void 0,l=function(e){return n.some((function(t){return!(!t.options.allowTouchMove||!t.options.allowTouchMove(e))}))},c=function(e){var t=e||window.event;return!!l(t.target)||(t.touches.length>1||(t.preventDefault&&t.preventDefault(),!1))};addEventListener("click",(e=>{window._overlasticAnchor=e.target.closest("a[data-turbo-frame^=overlay]")}),!0),addEventListener("turbo:before-fetch-request",(e=>{e.target.hasAttribute("cancel")&&(e.preventDefault(),e.target.removeAttribute("cancel"))}),!0),addEventListener("turbo:before-fetch-request",(e=>{e.detail.fetchOptions.headers["Overlay-Enabled"]="1"})),addEventListener("turbo:before-fetch-request",(e=>{if(!window._overlasticAnchor)return;const t=window._overlasticAnchor,o=t?.dataset?.overlayType,n=t?.dataset?.overlayTarget,r=t?.dataset?.overlayArgs;e.detail.fetchOptions.headers["Overlay-Initiator"]="1",o&&(e.detail.fetchOptions.headers["Overlay-Type"]=o),n&&(e.detail.fetchOptions.headers["Overlay-Target"]=n),r&&(e.detail.fetchOptions.headers["Overlay-Args"]=r),delete window._overlasticTarget})),addEventListener("turbo:before-fetch-request",(e=>{if(window._overlasticAnchor)return;const t=e.target.closest("turbo-frame[id^=overlay]");if(t){const o=t.dataset.overlayTarget,n=t.dataset?.overlayInitiator,r=t.dataset?.overlayType,i=t.dataset?.overlayArgs;e.detail.fetchOptions.headers["Overlay-Target"]=o,n&&(e.detail.fetchOptions.headers["Overlay-Initiator"]=n),r&&(e.detail.fetchOptions.headers["Overlay-Type"]=r),i&&(e.detail.fetchOptions.headers["Overlay-Args"]=i)}})),addEventListener("turbo:before-fetch-response",(async e=>{const t=e.detail.fetchResponse,o=t.response.headers.get("Overlay-Visit");if(!o)return;const n=await t.responseHTML,{redirected:r,statusCode:i}=t;return Turbo.session.visit(o,{shouldCacheSnapshot:!1,response:{redirected:r,statusCode:i,responseHTML:n}})}));class u extends HTMLElement{connectedCallback(){disableBodyScroll(this),this.addEventListener("click",(e=>this.close(e,!0))),this.querySelector(".overlastic-close").addEventListener("click",(e=>this.close(e)))}close(e,t=!1){t&&e.target!==this||(enableBodyScroll(this),setTimeout((()=>{this.remove()}),5))}}customElements.define("overlastic-dialog",u);customElements.define("overlastic-pane",class extends u{connectedCallback(){super.connectedCallback();const e=Turbo.navigator.history.location;window.modalVisitStack||(window.modalVisitStack=[]),window.modalVisitStack.push(e),Turbo.navigator.history.push(new URL(this.parentElement.src))}close(e,t=!1){t&&e.target!==this||(super.close(e,t),window.modalVisitStack.length>0&&Turbo.navigator.history.replace(window.modalVisitStack.pop()))}}),window.disableBodyScroll=function(t,u){if(t){if(!n.some((function(e){return e.targetElement===t}))){var v={targetElement:t,options:u||{}};n=[].concat(function(e){if(Array.isArray(e)){for(var t=0,o=Array(e.length);t<e.length;t++)o[t]=e[t];return o}return Array.from(e)}(n),[v]),o?window.requestAnimationFrame((function(){if(void 0===s){s={position:document.body.style.position,top:document.body.style.top,left:document.body.style.left};var e=window,t=e.scrollY,o=e.scrollX,n=e.innerHeight;document.body.style.position="fixed",document.body.style.top=-t,document.body.style.left=-o,setTimeout((function(){return window.requestAnimationFrame((function(){var e=n-window.innerHeight;e&&t>=n&&(document.body.style.top=-(t+e))}))}),300)}})):function(e){if(void 0===d){var t=!!e&&!0===e.reserveScrollBarGap,o=window.innerWidth-document.documentElement.clientWidth;if(t&&o>0){var n=parseInt(window.getComputedStyle(document.body).getPropertyValue("padding-right"),10);d=document.body.style.paddingRight,document.body.style.paddingRight=n+o+"px"}}void 0===a&&(a=document.body.style.overflow,document.body.style.overflow="hidden")}(u),o&&(t.ontouchstart=function(e){1===e.targetTouches.length&&(i=e.targetTouches[0].clientY)},t.ontouchmove=function(e){1===e.targetTouches.length&&function(e,t){var o=e.targetTouches[0].clientY-i;!l(e.target)&&(t&&0===t.scrollTop&&o>0||function(e){return!!e&&e.scrollHeight-e.scrollTop<=e.clientHeight}(t)&&o<0?c(e):e.stopPropagation())}(e,t)},r||(document.addEventListener("touchmove",c,e?{passive:!1}:void 0),r=!0))}}else console.error("disableBodyScroll unsuccessful - targetElement must be provided when calling disableBodyScroll on IOS devices.")},window.enableBodyScroll=function(t){t?(n=n.filter((function(e){return e.targetElement!==t})),o&&(t.ontouchstart=null,t.ontouchmove=null,r&&0===n.length&&(document.removeEventListener("touchmove",c,e?{passive:!1}:void 0),r=!1)),o?function(){if(void 0!==s){var e=-parseInt(document.body.style.top,10),t=-parseInt(document.body.style.left,10);document.body.style.position=s.position,document.body.style.top=s.top,document.body.style.left=s.left,window.scrollTo(t,e),s=void 0}}():(void 0!==d&&(document.body.style.paddingRight=d,d=void 0),void 0!==a&&(document.body.style.overflow=a,a=void 0))):console.error("enableBodyScroll unsuccessful - targetElement must be provided when calling enableBodyScroll on IOS devices.")};
1
+ var e=!1;if("undefined"!=typeof window){var t={get passive(){e=!0}};window.addEventListener("testPassive",null,t),window.removeEventListener("testPassive",null,t)}var o="undefined"!=typeof window&&window.navigator&&window.navigator.platform&&(/iP(ad|hone|od)/.test(window.navigator.platform)||"MacIntel"===window.navigator.platform&&window.navigator.maxTouchPoints>1),n=[],a=!1,i=-1,r=void 0,s=void 0,d=void 0,l=function(e){return n.some((function(t){return!(!t.options.allowTouchMove||!t.options.allowTouchMove(e))}))},c=function(e){var t=e||window.event;return!!l(t.target)||(t.touches.length>1||(t.preventDefault&&t.preventDefault(),!1))};addEventListener("click",(e=>{window._overlasticAnchor=e.target}),!0),addEventListener("turbo:before-fetch-request",(e=>{e.detail.fetchOptions.headers["Overlay-Enabled"]="1"})),addEventListener("turbo:before-fetch-request",(e=>{const t=e.target,o=t?.dataset?.overlayName,n=t?.dataset?.overlayType,a=t?.dataset?.overlayTarget,i=t?.dataset?.overlayArgs;o?.startsWith("overlay")&&(e.detail.fetchOptions.headers["Overlay-Initiator"]="1",e.detail.fetchOptions.headers["Overlay-Name"]=o,n&&(e.detail.fetchOptions.headers["Overlay-Type"]=n),a&&(e.detail.fetchOptions.headers["Overlay-Target"]=a),i&&(e.detail.fetchOptions.headers["Overlay-Args"]=i))})),addEventListener("turbo:before-fetch-request",(e=>{const t=document.querySelector("script[overlay]");if(t){const o=document.querySelector(`overlastic[id=${t.getAttribute("overlay")}]`);if(o){const t=o.id,n=o.dataset.overlayTarget,a=o.dataset?.overlayType,i=o.dataset?.overlayArgs;e.detail.fetchOptions.headers["Overlay-Name"]=t,e.detail.fetchOptions.headers["Overlay-Target"]=n,e.detail.fetchOptions.headers["Overlay-Initiator"]="1",a&&(e.detail.fetchOptions.headers["Overlay-Type"]=a),i&&(e.detail.fetchOptions.headers["Overlay-Args"]=i)}}})),addEventListener("turbo:before-fetch-request",(e=>{const t=window._overlasticAnchor,o=t.closest("overlastic");if(o&&!t.dataset.overlay&&!t.dataset.overlayName){const t=o.id,n=o.dataset.overlayTarget,a=o.dataset?.overlayInitiator,i=o.dataset?.overlayType,r=o.dataset?.overlayArgs;e.detail.fetchOptions.headers["Overlay-Name"]=t,e.detail.fetchOptions.headers["Overlay-Target"]=n,a&&(e.detail.fetchOptions.headers["Overlay-Initiator"]=a),i&&(e.detail.fetchOptions.headers["Overlay-Type"]=i),r&&(e.detail.fetchOptions.headers["Overlay-Args"]=r)}delete window._overlasticAnchor}));class v extends HTMLElement{connectedCallback(){disableBodyScroll(this),this.addEventListener("click",(e=>this.close(e,!0))),this.querySelector(".overlastic-close").addEventListener("click",(e=>this.close(e)))}close(e,t=!1){t&&e.target!==this||(enableBodyScroll(this),setTimeout((()=>{this.remove()}),5))}}customElements.define("overlastic-dialog",v);customElements.define("overlastic-pane",class extends v{connectedCallback(){super.connectedCallback();const e=Turbo.navigator.history.location;window.modalVisitStack||(window.modalVisitStack=[]),window.modalVisitStack.push(e),Turbo.navigator.history.push(new URL(this.parentElement.getAttribute("src")))}close(e,t=!1){t&&e.target!==this||(super.close(e,t),window.modalVisitStack.length>0&&Turbo.navigator.history.replace(window.modalVisitStack.pop()))}}),window.disableBodyScroll=function(t,v){if(t){if(!n.some((function(e){return e.targetElement===t}))){var u={targetElement:t,options:v||{}};n=[].concat(function(e){if(Array.isArray(e)){for(var t=0,o=Array(e.length);t<e.length;t++)o[t]=e[t];return o}return Array.from(e)}(n),[u]),o?window.requestAnimationFrame((function(){if(void 0===s){s={position:document.body.style.position,top:document.body.style.top,left:document.body.style.left};var e=window,t=e.scrollY,o=e.scrollX,n=e.innerHeight;document.body.style.position="fixed",document.body.style.top=-t,document.body.style.left=-o,setTimeout((function(){return window.requestAnimationFrame((function(){var e=n-window.innerHeight;e&&t>=n&&(document.body.style.top=-(t+e))}))}),300)}})):function(e){if(void 0===d){var t=!!e&&!0===e.reserveScrollBarGap,o=window.innerWidth-document.documentElement.clientWidth;if(t&&o>0){var n=parseInt(window.getComputedStyle(document.body).getPropertyValue("padding-right"),10);d=document.body.style.paddingRight,document.body.style.paddingRight=n+o+"px"}}void 0===r&&(r=document.body.style.overflow,document.body.style.overflow="hidden")}(v),o&&(t.ontouchstart=function(e){1===e.targetTouches.length&&(i=e.targetTouches[0].clientY)},t.ontouchmove=function(e){1===e.targetTouches.length&&function(e,t){var o=e.targetTouches[0].clientY-i;!l(e.target)&&(t&&0===t.scrollTop&&o>0||function(e){return!!e&&e.scrollHeight-e.scrollTop<=e.clientHeight}(t)&&o<0?c(e):e.stopPropagation())}(e,t)},a||(document.addEventListener("touchmove",c,e?{passive:!1}:void 0),a=!0))}}else console.error("disableBodyScroll unsuccessful - targetElement must be provided when calling disableBodyScroll on IOS devices.")},window.enableBodyScroll=function(t){t?(n=n.filter((function(e){return e.targetElement!==t})),o&&(t.ontouchstart=null,t.ontouchmove=null,a&&0===n.length&&(document.removeEventListener("touchmove",c,e?{passive:!1}:void 0),a=!1)),o?function(){if(void 0!==s){var e=-parseInt(document.body.style.top,10),t=-parseInt(document.body.style.left,10);document.body.style.position=s.position,document.body.style.top=s.top,document.body.style.left=s.left,window.scrollTo(t,e),s=void 0}}():(void 0!==d&&(document.body.style.paddingRight=d,d=void 0),void 0!==r&&(document.body.style.overflow=r,r=void 0))):console.error("enableBodyScroll unsuccessful - targetElement must be provided when calling enableBodyScroll on IOS devices.")};
2
2
  //# sourceMappingURL=overlastic.min.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"overlastic.min.js","sources":["../../../node_modules/body-scroll-lock/lib/bodyScrollLock.esm.js","../../javascript/overlastic/clickInterceptor.js","../../javascript/overlastic/dialogElement.js","../../javascript/overlastic/paneElement.js","../../javascript/overlastic/index.js"],"sourcesContent":["function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }\n\n// Older browsers don't support event options, feature detect it.\n\n// Adopted and modified solution from Bohdan Didukh (2017)\n// https://stackoverflow.com/questions/41594997/ios-10-safari-prevent-scrolling-behind-a-fixed-overlay-and-maintain-scroll-posi\n\nvar hasPassiveEvents = false;\nif (typeof window !== 'undefined') {\n var passiveTestOptions = {\n get passive() {\n hasPassiveEvents = true;\n return undefined;\n }\n };\n window.addEventListener('testPassive', null, passiveTestOptions);\n window.removeEventListener('testPassive', null, passiveTestOptions);\n}\n\nvar isIosDevice = typeof window !== 'undefined' && window.navigator && window.navigator.platform && (/iP(ad|hone|od)/.test(window.navigator.platform) || window.navigator.platform === 'MacIntel' && window.navigator.maxTouchPoints > 1);\n\n\nvar locks = [];\nvar documentListenerAdded = false;\nvar initialClientY = -1;\nvar previousBodyOverflowSetting = void 0;\nvar previousBodyPosition = void 0;\nvar previousBodyPaddingRight = void 0;\n\n// returns true if `el` should be allowed to receive touchmove events.\nvar allowTouchMove = function allowTouchMove(el) {\n return locks.some(function (lock) {\n if (lock.options.allowTouchMove && lock.options.allowTouchMove(el)) {\n return true;\n }\n\n return false;\n });\n};\n\nvar preventDefault = function preventDefault(rawEvent) {\n var e = rawEvent || window.event;\n\n // For the case whereby consumers adds a touchmove event listener to document.\n // Recall that we do document.addEventListener('touchmove', preventDefault, { passive: false })\n // in disableBodyScroll - so if we provide this opportunity to allowTouchMove, then\n // the touchmove event on document will break.\n if (allowTouchMove(e.target)) {\n return true;\n }\n\n // Do not prevent if the event has more than one touch (usually meaning this is a multi touch gesture like pinch to zoom).\n if (e.touches.length > 1) return true;\n\n if (e.preventDefault) e.preventDefault();\n\n return false;\n};\n\nvar setOverflowHidden = function setOverflowHidden(options) {\n // If previousBodyPaddingRight is already set, don't set it again.\n if (previousBodyPaddingRight === undefined) {\n var _reserveScrollBarGap = !!options && options.reserveScrollBarGap === true;\n var scrollBarGap = window.innerWidth - document.documentElement.clientWidth;\n\n if (_reserveScrollBarGap && scrollBarGap > 0) {\n var computedBodyPaddingRight = parseInt(window.getComputedStyle(document.body).getPropertyValue('padding-right'), 10);\n previousBodyPaddingRight = document.body.style.paddingRight;\n document.body.style.paddingRight = computedBodyPaddingRight + scrollBarGap + 'px';\n }\n }\n\n // If previousBodyOverflowSetting is already set, don't set it again.\n if (previousBodyOverflowSetting === undefined) {\n previousBodyOverflowSetting = document.body.style.overflow;\n document.body.style.overflow = 'hidden';\n }\n};\n\nvar restoreOverflowSetting = function restoreOverflowSetting() {\n if (previousBodyPaddingRight !== undefined) {\n document.body.style.paddingRight = previousBodyPaddingRight;\n\n // Restore previousBodyPaddingRight to undefined so setOverflowHidden knows it\n // can be set again.\n previousBodyPaddingRight = undefined;\n }\n\n if (previousBodyOverflowSetting !== undefined) {\n document.body.style.overflow = previousBodyOverflowSetting;\n\n // Restore previousBodyOverflowSetting to undefined\n // so setOverflowHidden knows it can be set again.\n previousBodyOverflowSetting = undefined;\n }\n};\n\nvar setPositionFixed = function setPositionFixed() {\n return window.requestAnimationFrame(function () {\n // If previousBodyPosition is already set, don't set it again.\n if (previousBodyPosition === undefined) {\n previousBodyPosition = {\n position: document.body.style.position,\n top: document.body.style.top,\n left: document.body.style.left\n };\n\n // Update the dom inside an animation frame \n var _window = window,\n scrollY = _window.scrollY,\n scrollX = _window.scrollX,\n innerHeight = _window.innerHeight;\n\n document.body.style.position = 'fixed';\n document.body.style.top = -scrollY;\n document.body.style.left = -scrollX;\n\n setTimeout(function () {\n return window.requestAnimationFrame(function () {\n // Attempt to check if the bottom bar appeared due to the position change\n var bottomBarHeight = innerHeight - window.innerHeight;\n if (bottomBarHeight && scrollY >= innerHeight) {\n // Move the content further up so that the bottom bar doesn't hide it\n document.body.style.top = -(scrollY + bottomBarHeight);\n }\n });\n }, 300);\n }\n });\n};\n\nvar restorePositionSetting = function restorePositionSetting() {\n if (previousBodyPosition !== undefined) {\n // Convert the position from \"px\" to Int\n var y = -parseInt(document.body.style.top, 10);\n var x = -parseInt(document.body.style.left, 10);\n\n // Restore styles\n document.body.style.position = previousBodyPosition.position;\n document.body.style.top = previousBodyPosition.top;\n document.body.style.left = previousBodyPosition.left;\n\n // Restore scroll\n window.scrollTo(x, y);\n\n previousBodyPosition = undefined;\n }\n};\n\n// https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollHeight#Problems_and_solutions\nvar isTargetElementTotallyScrolled = function isTargetElementTotallyScrolled(targetElement) {\n return targetElement ? targetElement.scrollHeight - targetElement.scrollTop <= targetElement.clientHeight : false;\n};\n\nvar handleScroll = function handleScroll(event, targetElement) {\n var clientY = event.targetTouches[0].clientY - initialClientY;\n\n if (allowTouchMove(event.target)) {\n return false;\n }\n\n if (targetElement && targetElement.scrollTop === 0 && clientY > 0) {\n // element is at the top of its scroll.\n return preventDefault(event);\n }\n\n if (isTargetElementTotallyScrolled(targetElement) && clientY < 0) {\n // element is at the bottom of its scroll.\n return preventDefault(event);\n }\n\n event.stopPropagation();\n return true;\n};\n\nexport var disableBodyScroll = function disableBodyScroll(targetElement, options) {\n // targetElement must be provided\n if (!targetElement) {\n // eslint-disable-next-line no-console\n console.error('disableBodyScroll unsuccessful - targetElement must be provided when calling disableBodyScroll on IOS devices.');\n return;\n }\n\n // disableBodyScroll must not have been called on this targetElement before\n if (locks.some(function (lock) {\n return lock.targetElement === targetElement;\n })) {\n return;\n }\n\n var lock = {\n targetElement: targetElement,\n options: options || {}\n };\n\n locks = [].concat(_toConsumableArray(locks), [lock]);\n\n if (isIosDevice) {\n setPositionFixed();\n } else {\n setOverflowHidden(options);\n }\n\n if (isIosDevice) {\n targetElement.ontouchstart = function (event) {\n if (event.targetTouches.length === 1) {\n // detect single touch.\n initialClientY = event.targetTouches[0].clientY;\n }\n };\n targetElement.ontouchmove = function (event) {\n if (event.targetTouches.length === 1) {\n // detect single touch.\n handleScroll(event, targetElement);\n }\n };\n\n if (!documentListenerAdded) {\n document.addEventListener('touchmove', preventDefault, hasPassiveEvents ? { passive: false } : undefined);\n documentListenerAdded = true;\n }\n }\n};\n\nexport var clearAllBodyScrollLocks = function clearAllBodyScrollLocks() {\n if (isIosDevice) {\n // Clear all locks ontouchstart/ontouchmove handlers, and the references.\n locks.forEach(function (lock) {\n lock.targetElement.ontouchstart = null;\n lock.targetElement.ontouchmove = null;\n });\n\n if (documentListenerAdded) {\n document.removeEventListener('touchmove', preventDefault, hasPassiveEvents ? { passive: false } : undefined);\n documentListenerAdded = false;\n }\n\n // Reset initial clientY.\n initialClientY = -1;\n }\n\n if (isIosDevice) {\n restorePositionSetting();\n } else {\n restoreOverflowSetting();\n }\n\n locks = [];\n};\n\nexport var enableBodyScroll = function enableBodyScroll(targetElement) {\n if (!targetElement) {\n // eslint-disable-next-line no-console\n console.error('enableBodyScroll unsuccessful - targetElement must be provided when calling enableBodyScroll on IOS devices.');\n return;\n }\n\n locks = locks.filter(function (lock) {\n return lock.targetElement !== targetElement;\n });\n\n if (isIosDevice) {\n targetElement.ontouchstart = null;\n targetElement.ontouchmove = null;\n\n if (documentListenerAdded && locks.length === 0) {\n document.removeEventListener('touchmove', preventDefault, hasPassiveEvents ? { passive: false } : undefined);\n documentListenerAdded = false;\n }\n }\n\n if (isIosDevice) {\n restorePositionSetting();\n } else {\n restoreOverflowSetting();\n }\n};\n\n","// Save the clicked overlay link element for use down the line.\naddEventListener(\"click\", event => {\n window._overlasticAnchor = event.target.closest(\"a[data-turbo-frame^=overlay]\")\n}, true)\n\n// In order to respect frame behavior, overlay stream responses replace whole frames and\n// come with the correct src. This triggers the frame controller to attempt an eager load.\n// We don't want that for overlays, so we cancel those requests.\naddEventListener(\"turbo:before-fetch-request\", event => {\n if (!event.target.hasAttribute(\"cancel\")) return\n\n event.preventDefault()\n\n event.target.removeAttribute(\"cancel\")\n}, true)\n\n// Allow progressive enhancement by telling the server if a request is handled by Turbo.\naddEventListener(\"turbo:before-fetch-request\", event => {\n event.detail.fetchOptions.headers[\"Overlay-Enabled\"] = \"1\"\n})\n\n// When an overlay anchor is clicked,\n// send its type, target and args along with the frame request.\naddEventListener(\"turbo:before-fetch-request\", event => {\n if (!window._overlasticAnchor) return\n\n const anchor = window._overlasticAnchor\n const type = anchor?.dataset?.overlayType\n const target = anchor?.dataset?.overlayTarget\n const args = anchor?.dataset?.overlayArgs\n\n event.detail.fetchOptions.headers[\"Overlay-Initiator\"] = \"1\"\n\n if (type) {\n event.detail.fetchOptions.headers[\"Overlay-Type\"] = type\n }\n\n if (target) {\n event.detail.fetchOptions.headers[\"Overlay-Target\"] = target\n }\n\n if (args) {\n event.detail.fetchOptions.headers[\"Overlay-Args\"] = args\n }\n\n delete window._overlasticTarget\n})\n\n// When any other element triggers a fetch,\n// send the current overlay's target along with the frame request.\naddEventListener(\"turbo:before-fetch-request\", event => {\n if (window._overlasticAnchor) return\n\n const frame = event.target.closest(\"turbo-frame[id^=overlay]\")\n\n if (frame) {\n const target = frame.dataset.overlayTarget\n const initiator = frame.dataset?.overlayInitiator\n const type = frame.dataset?.overlayType\n const args = frame.dataset?.overlayArgs\n\n event.detail.fetchOptions.headers[\"Overlay-Target\"] = target\n\n if (initiator) {\n event.detail.fetchOptions.headers[\"Overlay-Initiator\"] = initiator\n }\n\n if (type) {\n event.detail.fetchOptions.headers[\"Overlay-Type\"] = type\n }\n\n if (args) {\n event.detail.fetchOptions.headers[\"Overlay-Args\"] = args\n }\n }\n})\n\n// Handle frame-to-visit promotions when the server asks for it.\naddEventListener(\"turbo:before-fetch-response\", async event => {\n const fetchResponse = event.detail.fetchResponse\n const visit = fetchResponse.response.headers.get(\"Overlay-Visit\")\n\n if (!visit) return\n\n const responseHTML = await fetchResponse.responseHTML\n const { redirected, statusCode } = fetchResponse\n\n return Turbo.session.visit(visit, { shouldCacheSnapshot: false, response: { redirected, statusCode, responseHTML } })\n})\n","export default class DialogElement extends HTMLElement {\n connectedCallback() {\n disableBodyScroll(this)\n\n this.addEventListener(\"click\", event => this.close(event, true))\n this.querySelector(\".overlastic-close\").addEventListener(\"click\", event => this.close(event))\n }\n\n close(event, self = false) {\n if (self && event.target !== this) return\n\n enableBodyScroll(this)\n\n // Avoid removing before sending dispatching other events (like form submissions)\n setTimeout(() => {\n this.remove()\n }, 5)\n }\n}\n\ncustomElements.define(\"overlastic-dialog\", DialogElement)\n","import DialogElement from \"./dialogElement\"\n\nclass PaneElement extends DialogElement {\n connectedCallback() {\n super.connectedCallback()\n\n const lastVisit = Turbo.navigator.history.location\n\n if (!window.modalVisitStack) {\n window.modalVisitStack = []\n }\n\n window.modalVisitStack.push(lastVisit)\n Turbo.navigator.history.push(new URL(this.parentElement.src))\n }\n\n close(event, self = false) {\n if (self && event.target !== this) return\n\n super.close(event, self)\n\n if (window.modalVisitStack.length > 0) {\n Turbo.navigator.history.replace(window.modalVisitStack.pop())\n }\n }\n}\n\ncustomElements.define(\"overlastic-pane\", PaneElement)\n","import { disableBodyScroll, enableBodyScroll } from \"body-scroll-lock\"\n\nimport \"./clickInterceptor\"\nimport \"./dialogElement\"\nimport \"./paneElement\"\n\nwindow.disableBodyScroll = disableBodyScroll\nwindow.enableBodyScroll = enableBodyScroll\n"],"names":["hasPassiveEvents","window","passiveTestOptions","passive","addEventListener","removeEventListener","isIosDevice","navigator","platform","test","maxTouchPoints","locks","documentListenerAdded","initialClientY","previousBodyOverflowSetting","previousBodyPosition","previousBodyPaddingRight","allowTouchMove","el","some","lock","options","preventDefault","rawEvent","e","event","target","touches","length","_overlasticAnchor","closest","hasAttribute","removeAttribute","detail","fetchOptions","headers","anchor","type","dataset","overlayType","overlayTarget","args","overlayArgs","_overlasticTarget","frame","initiator","overlayInitiator","async","fetchResponse","visit","response","get","responseHTML","redirected","statusCode","Turbo","session","shouldCacheSnapshot","DialogElement","HTMLElement","[object Object]","disableBodyScroll","this","close","querySelector","self","enableBodyScroll","setTimeout","remove","customElements","define","super","connectedCallback","lastVisit","history","location","modalVisitStack","push","URL","parentElement","src","replace","pop","targetElement","concat","arr","Array","isArray","i","arr2","from","_toConsumableArray","requestAnimationFrame","undefined","position","document","body","style","top","left","_window","scrollY","scrollX","innerHeight","bottomBarHeight","_reserveScrollBarGap","reserveScrollBarGap","scrollBarGap","innerWidth","documentElement","clientWidth","computedBodyPaddingRight","parseInt","getComputedStyle","getPropertyValue","paddingRight","overflow","setOverflowHidden","ontouchstart","targetTouches","clientY","ontouchmove","scrollTop","scrollHeight","clientHeight","isTargetElementTotallyScrolled","stopPropagation","handleScroll","console","error","filter","y","x","scrollTo","restorePositionSetting"],"mappings":"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"}
1
+ {"version":3,"file":"overlastic.min.js","sources":["../../../node_modules/body-scroll-lock/lib/bodyScrollLock.esm.js","../../javascript/overlastic/clickInterceptor.js","../../javascript/overlastic/dialogElement.js","../../javascript/overlastic/paneElement.js","../../javascript/overlastic/index.js"],"sourcesContent":["function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }\n\n// Older browsers don't support event options, feature detect it.\n\n// Adopted and modified solution from Bohdan Didukh (2017)\n// https://stackoverflow.com/questions/41594997/ios-10-safari-prevent-scrolling-behind-a-fixed-overlay-and-maintain-scroll-posi\n\nvar hasPassiveEvents = false;\nif (typeof window !== 'undefined') {\n var passiveTestOptions = {\n get passive() {\n hasPassiveEvents = true;\n return undefined;\n }\n };\n window.addEventListener('testPassive', null, passiveTestOptions);\n window.removeEventListener('testPassive', null, passiveTestOptions);\n}\n\nvar isIosDevice = typeof window !== 'undefined' && window.navigator && window.navigator.platform && (/iP(ad|hone|od)/.test(window.navigator.platform) || window.navigator.platform === 'MacIntel' && window.navigator.maxTouchPoints > 1);\n\n\nvar locks = [];\nvar documentListenerAdded = false;\nvar initialClientY = -1;\nvar previousBodyOverflowSetting = void 0;\nvar previousBodyPosition = void 0;\nvar previousBodyPaddingRight = void 0;\n\n// returns true if `el` should be allowed to receive touchmove events.\nvar allowTouchMove = function allowTouchMove(el) {\n return locks.some(function (lock) {\n if (lock.options.allowTouchMove && lock.options.allowTouchMove(el)) {\n return true;\n }\n\n return false;\n });\n};\n\nvar preventDefault = function preventDefault(rawEvent) {\n var e = rawEvent || window.event;\n\n // For the case whereby consumers adds a touchmove event listener to document.\n // Recall that we do document.addEventListener('touchmove', preventDefault, { passive: false })\n // in disableBodyScroll - so if we provide this opportunity to allowTouchMove, then\n // the touchmove event on document will break.\n if (allowTouchMove(e.target)) {\n return true;\n }\n\n // Do not prevent if the event has more than one touch (usually meaning this is a multi touch gesture like pinch to zoom).\n if (e.touches.length > 1) return true;\n\n if (e.preventDefault) e.preventDefault();\n\n return false;\n};\n\nvar setOverflowHidden = function setOverflowHidden(options) {\n // If previousBodyPaddingRight is already set, don't set it again.\n if (previousBodyPaddingRight === undefined) {\n var _reserveScrollBarGap = !!options && options.reserveScrollBarGap === true;\n var scrollBarGap = window.innerWidth - document.documentElement.clientWidth;\n\n if (_reserveScrollBarGap && scrollBarGap > 0) {\n var computedBodyPaddingRight = parseInt(window.getComputedStyle(document.body).getPropertyValue('padding-right'), 10);\n previousBodyPaddingRight = document.body.style.paddingRight;\n document.body.style.paddingRight = computedBodyPaddingRight + scrollBarGap + 'px';\n }\n }\n\n // If previousBodyOverflowSetting is already set, don't set it again.\n if (previousBodyOverflowSetting === undefined) {\n previousBodyOverflowSetting = document.body.style.overflow;\n document.body.style.overflow = 'hidden';\n }\n};\n\nvar restoreOverflowSetting = function restoreOverflowSetting() {\n if (previousBodyPaddingRight !== undefined) {\n document.body.style.paddingRight = previousBodyPaddingRight;\n\n // Restore previousBodyPaddingRight to undefined so setOverflowHidden knows it\n // can be set again.\n previousBodyPaddingRight = undefined;\n }\n\n if (previousBodyOverflowSetting !== undefined) {\n document.body.style.overflow = previousBodyOverflowSetting;\n\n // Restore previousBodyOverflowSetting to undefined\n // so setOverflowHidden knows it can be set again.\n previousBodyOverflowSetting = undefined;\n }\n};\n\nvar setPositionFixed = function setPositionFixed() {\n return window.requestAnimationFrame(function () {\n // If previousBodyPosition is already set, don't set it again.\n if (previousBodyPosition === undefined) {\n previousBodyPosition = {\n position: document.body.style.position,\n top: document.body.style.top,\n left: document.body.style.left\n };\n\n // Update the dom inside an animation frame \n var _window = window,\n scrollY = _window.scrollY,\n scrollX = _window.scrollX,\n innerHeight = _window.innerHeight;\n\n document.body.style.position = 'fixed';\n document.body.style.top = -scrollY;\n document.body.style.left = -scrollX;\n\n setTimeout(function () {\n return window.requestAnimationFrame(function () {\n // Attempt to check if the bottom bar appeared due to the position change\n var bottomBarHeight = innerHeight - window.innerHeight;\n if (bottomBarHeight && scrollY >= innerHeight) {\n // Move the content further up so that the bottom bar doesn't hide it\n document.body.style.top = -(scrollY + bottomBarHeight);\n }\n });\n }, 300);\n }\n });\n};\n\nvar restorePositionSetting = function restorePositionSetting() {\n if (previousBodyPosition !== undefined) {\n // Convert the position from \"px\" to Int\n var y = -parseInt(document.body.style.top, 10);\n var x = -parseInt(document.body.style.left, 10);\n\n // Restore styles\n document.body.style.position = previousBodyPosition.position;\n document.body.style.top = previousBodyPosition.top;\n document.body.style.left = previousBodyPosition.left;\n\n // Restore scroll\n window.scrollTo(x, y);\n\n previousBodyPosition = undefined;\n }\n};\n\n// https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollHeight#Problems_and_solutions\nvar isTargetElementTotallyScrolled = function isTargetElementTotallyScrolled(targetElement) {\n return targetElement ? targetElement.scrollHeight - targetElement.scrollTop <= targetElement.clientHeight : false;\n};\n\nvar handleScroll = function handleScroll(event, targetElement) {\n var clientY = event.targetTouches[0].clientY - initialClientY;\n\n if (allowTouchMove(event.target)) {\n return false;\n }\n\n if (targetElement && targetElement.scrollTop === 0 && clientY > 0) {\n // element is at the top of its scroll.\n return preventDefault(event);\n }\n\n if (isTargetElementTotallyScrolled(targetElement) && clientY < 0) {\n // element is at the bottom of its scroll.\n return preventDefault(event);\n }\n\n event.stopPropagation();\n return true;\n};\n\nexport var disableBodyScroll = function disableBodyScroll(targetElement, options) {\n // targetElement must be provided\n if (!targetElement) {\n // eslint-disable-next-line no-console\n console.error('disableBodyScroll unsuccessful - targetElement must be provided when calling disableBodyScroll on IOS devices.');\n return;\n }\n\n // disableBodyScroll must not have been called on this targetElement before\n if (locks.some(function (lock) {\n return lock.targetElement === targetElement;\n })) {\n return;\n }\n\n var lock = {\n targetElement: targetElement,\n options: options || {}\n };\n\n locks = [].concat(_toConsumableArray(locks), [lock]);\n\n if (isIosDevice) {\n setPositionFixed();\n } else {\n setOverflowHidden(options);\n }\n\n if (isIosDevice) {\n targetElement.ontouchstart = function (event) {\n if (event.targetTouches.length === 1) {\n // detect single touch.\n initialClientY = event.targetTouches[0].clientY;\n }\n };\n targetElement.ontouchmove = function (event) {\n if (event.targetTouches.length === 1) {\n // detect single touch.\n handleScroll(event, targetElement);\n }\n };\n\n if (!documentListenerAdded) {\n document.addEventListener('touchmove', preventDefault, hasPassiveEvents ? { passive: false } : undefined);\n documentListenerAdded = true;\n }\n }\n};\n\nexport var clearAllBodyScrollLocks = function clearAllBodyScrollLocks() {\n if (isIosDevice) {\n // Clear all locks ontouchstart/ontouchmove handlers, and the references.\n locks.forEach(function (lock) {\n lock.targetElement.ontouchstart = null;\n lock.targetElement.ontouchmove = null;\n });\n\n if (documentListenerAdded) {\n document.removeEventListener('touchmove', preventDefault, hasPassiveEvents ? { passive: false } : undefined);\n documentListenerAdded = false;\n }\n\n // Reset initial clientY.\n initialClientY = -1;\n }\n\n if (isIosDevice) {\n restorePositionSetting();\n } else {\n restoreOverflowSetting();\n }\n\n locks = [];\n};\n\nexport var enableBodyScroll = function enableBodyScroll(targetElement) {\n if (!targetElement) {\n // eslint-disable-next-line no-console\n console.error('enableBodyScroll unsuccessful - targetElement must be provided when calling enableBodyScroll on IOS devices.');\n return;\n }\n\n locks = locks.filter(function (lock) {\n return lock.targetElement !== targetElement;\n });\n\n if (isIosDevice) {\n targetElement.ontouchstart = null;\n targetElement.ontouchmove = null;\n\n if (documentListenerAdded && locks.length === 0) {\n document.removeEventListener('touchmove', preventDefault, hasPassiveEvents ? { passive: false } : undefined);\n documentListenerAdded = false;\n }\n }\n\n if (isIosDevice) {\n restorePositionSetting();\n } else {\n restoreOverflowSetting();\n }\n};\n\n","// Save the clicked element for use down the line.\naddEventListener(\"click\", event => {\n window._overlasticAnchor = event.target\n}, true)\n\n// Allow progressive enhancement by telling the server if a request is handled by Turbo.\naddEventListener(\"turbo:before-fetch-request\", event => {\n event.detail.fetchOptions.headers[\"Overlay-Enabled\"] = \"1\"\n})\n\n// When an overlay anchor is clicked,\n// send its type, target and args along with the visit request.\naddEventListener(\"turbo:before-fetch-request\", event => {\n const anchor = event.target\n const name = anchor?.dataset?.overlayName\n const type = anchor?.dataset?.overlayType\n const target = anchor?.dataset?.overlayTarget\n const args = anchor?.dataset?.overlayArgs\n\n if (name?.startsWith(\"overlay\")) {\n event.detail.fetchOptions.headers[\"Overlay-Initiator\"] = \"1\"\n event.detail.fetchOptions.headers[\"Overlay-Name\"] = name\n\n if (type) {\n event.detail.fetchOptions.headers[\"Overlay-Type\"] = type\n }\n\n if (target) {\n event.detail.fetchOptions.headers[\"Overlay-Target\"] = target\n }\n\n if (args) {\n event.detail.fetchOptions.headers[\"Overlay-Args\"] = args\n }\n }\n})\n\n// When the redirect script triggers a fetch,\n// send the current overlay's target along with the visit request.\naddEventListener(\"turbo:before-fetch-request\", event => {\n const script = document.querySelector(\"script[overlay]\")\n\n if (script) {\n const overlay = document.querySelector(`overlastic[id=${script.getAttribute(\"overlay\")}]`)\n\n if (overlay) {\n const name = overlay.id\n const target = overlay.dataset.overlayTarget\n const type = overlay.dataset?.overlayType\n const args = overlay.dataset?.overlayArgs\n\n event.detail.fetchOptions.headers[\"Overlay-Name\"] = name\n event.detail.fetchOptions.headers[\"Overlay-Target\"] = target\n event.detail.fetchOptions.headers[\"Overlay-Initiator\"] = \"1\"\n\n if (type) {\n event.detail.fetchOptions.headers[\"Overlay-Type\"] = type\n }\n\n if (args) {\n event.detail.fetchOptions.headers[\"Overlay-Args\"] = args\n }\n }\n }\n})\n\n// When any other element triggers a fetch,\n// send the current overlay's target along with the visit request.\naddEventListener(\"turbo:before-fetch-request\", event => {\n const anchor = window._overlasticAnchor\n const overlay = anchor.closest(\"overlastic\")\n\n if (overlay && !anchor.dataset.overlay && !anchor.dataset.overlayName) {\n const name = overlay.id\n const target = overlay.dataset.overlayTarget\n const initiator = overlay.dataset?.overlayInitiator\n const type = overlay.dataset?.overlayType\n const args = overlay.dataset?.overlayArgs\n\n event.detail.fetchOptions.headers[\"Overlay-Name\"] = name\n event.detail.fetchOptions.headers[\"Overlay-Target\"] = target\n\n if (initiator) {\n event.detail.fetchOptions.headers[\"Overlay-Initiator\"] = initiator\n }\n\n if (type) {\n event.detail.fetchOptions.headers[\"Overlay-Type\"] = type\n }\n\n if (args) {\n event.detail.fetchOptions.headers[\"Overlay-Args\"] = args\n }\n }\n\n delete window._overlasticAnchor\n})\n","export default class DialogElement extends HTMLElement {\n connectedCallback() {\n disableBodyScroll(this)\n\n this.addEventListener(\"click\", event => this.close(event, true))\n this.querySelector(\".overlastic-close\").addEventListener(\"click\", event => this.close(event))\n }\n\n close(event, self = false) {\n if (self && event.target !== this) return\n\n enableBodyScroll(this)\n\n // Avoid removing before sending dispatching other events (like form submissions)\n setTimeout(() => {\n this.remove()\n }, 5)\n }\n}\n\ncustomElements.define(\"overlastic-dialog\", DialogElement)\n","import DialogElement from \"./dialogElement\"\n\nclass PaneElement extends DialogElement {\n connectedCallback() {\n super.connectedCallback()\n\n const lastVisit = Turbo.navigator.history.location\n\n if (!window.modalVisitStack) {\n window.modalVisitStack = []\n }\n\n window.modalVisitStack.push(lastVisit)\n Turbo.navigator.history.push(new URL(this.parentElement.getAttribute(\"src\")))\n }\n\n close(event, self = false) {\n if (self && event.target !== this) return\n\n super.close(event, self)\n\n if (window.modalVisitStack.length > 0) {\n Turbo.navigator.history.replace(window.modalVisitStack.pop())\n }\n }\n}\n\ncustomElements.define(\"overlastic-pane\", PaneElement)\n","import { disableBodyScroll, enableBodyScroll } from \"body-scroll-lock\"\n\nimport \"./clickInterceptor\"\nimport \"./dialogElement\"\nimport \"./paneElement\"\n\nwindow.disableBodyScroll = disableBodyScroll\nwindow.enableBodyScroll = enableBodyScroll\n"],"names":["hasPassiveEvents","window","passiveTestOptions","passive","addEventListener","removeEventListener","isIosDevice","navigator","platform","test","maxTouchPoints","locks","documentListenerAdded","initialClientY","previousBodyOverflowSetting","previousBodyPosition","previousBodyPaddingRight","allowTouchMove","el","some","lock","options","preventDefault","rawEvent","e","event","target","touches","length","_overlasticAnchor","detail","fetchOptions","headers","anchor","name","dataset","overlayName","type","overlayType","overlayTarget","args","overlayArgs","startsWith","script","document","querySelector","overlay","getAttribute","id","closest","initiator","overlayInitiator","DialogElement","HTMLElement","[object Object]","disableBodyScroll","this","close","self","enableBodyScroll","setTimeout","remove","customElements","define","super","connectedCallback","lastVisit","Turbo","history","location","modalVisitStack","push","URL","parentElement","replace","pop","targetElement","concat","arr","Array","isArray","i","arr2","from","_toConsumableArray","requestAnimationFrame","undefined","position","body","style","top","left","_window","scrollY","scrollX","innerHeight","bottomBarHeight","_reserveScrollBarGap","reserveScrollBarGap","scrollBarGap","innerWidth","documentElement","clientWidth","computedBodyPaddingRight","parseInt","getComputedStyle","getPropertyValue","paddingRight","overflow","setOverflowHidden","ontouchstart","targetTouches","clientY","ontouchmove","scrollTop","scrollHeight","clientHeight","isTargetElementTotallyScrolled","stopPropagation","handleScroll","console","error","filter","y","x","scrollTo","restorePositionSetting"],"mappings":"AAOA,IAAIA,GAAmB,EACvB,GAAsB,oBAAXC,OAAwB,CACjC,IAAIC,EAAqB,CACvBC,cACEH,GAAmB,IAIvBC,OAAOG,iBAAiB,cAAe,KAAMF,GAC7CD,OAAOI,oBAAoB,cAAe,KAAMH,GAGlD,IAAII,EAAgC,oBAAXL,QAA0BA,OAAOM,WAAaN,OAAOM,UAAUC,WAAa,iBAAiBC,KAAKR,OAAOM,UAAUC,WAA2C,aAA9BP,OAAOM,UAAUC,UAA2BP,OAAOM,UAAUG,eAAiB,GAGnOC,EAAQ,GACRC,GAAwB,EACxBC,GAAkB,EAClBC,OAA8B,EAC9BC,OAAuB,EACvBC,OAA2B,EAG3BC,EAAiB,SAAwBC,GAC3C,OAAOP,EAAMQ,MAAK,SAAUC,GAC1B,SAAIA,EAAKC,QAAQJ,iBAAkBG,EAAKC,QAAQJ,eAAeC,QAQ/DI,EAAiB,SAAwBC,GAC3C,IAAIC,EAAID,GAAYtB,OAAOwB,MAM3B,QAAIR,EAAeO,EAAEE,UAKjBF,EAAEG,QAAQC,OAAS,IAEnBJ,EAAEF,gBAAgBE,EAAEF,kBAEjB,KCvDTlB,iBAAiB,SAASqB,IACxBxB,OAAO4B,kBAAoBJ,EAAMC,UAChC,GAGHtB,iBAAiB,8BAA8BqB,IAC7CA,EAAMK,OAAOC,aAAaC,QAAQ,mBAAqB,OAKzD5B,iBAAiB,8BAA8BqB,IAC7C,MAAMQ,EAASR,EAAMC,OACfQ,EAAOD,GAAQE,SAASC,YACxBC,EAAOJ,GAAQE,SAASG,YACxBZ,EAASO,GAAQE,SAASI,cAC1BC,EAAOP,GAAQE,SAASM,YAE1BP,GAAMQ,WAAW,aACnBjB,EAAMK,OAAOC,aAAaC,QAAQ,qBAAuB,IACzDP,EAAMK,OAAOC,aAAaC,QAAQ,gBAAkBE,EAEhDG,IACFZ,EAAMK,OAAOC,aAAaC,QAAQ,gBAAkBK,GAGlDX,IACFD,EAAMK,OAAOC,aAAaC,QAAQ,kBAAoBN,GAGpDc,IACFf,EAAMK,OAAOC,aAAaC,QAAQ,gBAAkBQ,OAO1DpC,iBAAiB,8BAA8BqB,IAC7C,MAAMkB,EAASC,SAASC,cAAc,mBAEtC,GAAIF,EAAQ,CACV,MAAMG,EAAUF,SAASC,cAAc,iBAAiBF,EAAOI,aAAa,eAE5E,GAAID,EAAS,CACX,MAAMZ,EAAOY,EAAQE,GACftB,EAASoB,EAAQX,QAAQI,cACzBF,EAAOS,EAAQX,SAASG,YACxBE,EAAOM,EAAQX,SAASM,YAE9BhB,EAAMK,OAAOC,aAAaC,QAAQ,gBAAkBE,EACpDT,EAAMK,OAAOC,aAAaC,QAAQ,kBAAoBN,EACtDD,EAAMK,OAAOC,aAAaC,QAAQ,qBAAuB,IAErDK,IACFZ,EAAMK,OAAOC,aAAaC,QAAQ,gBAAkBK,GAGlDG,IACFf,EAAMK,OAAOC,aAAaC,QAAQ,gBAAkBQ,QAQ5DpC,iBAAiB,8BAA8BqB,IAC7C,MAAMQ,EAAShC,OAAO4B,kBAChBiB,EAAUb,EAAOgB,QAAQ,cAE/B,GAAIH,IAAYb,EAAOE,QAAQW,UAAYb,EAAOE,QAAQC,YAAa,CACrE,MAAMF,EAAOY,EAAQE,GACftB,EAASoB,EAAQX,QAAQI,cACzBW,EAAYJ,EAAQX,SAASgB,iBAC7Bd,EAAOS,EAAQX,SAASG,YACxBE,EAAOM,EAAQX,SAASM,YAE9BhB,EAAMK,OAAOC,aAAaC,QAAQ,gBAAkBE,EACpDT,EAAMK,OAAOC,aAAaC,QAAQ,kBAAoBN,EAElDwB,IACFzB,EAAMK,OAAOC,aAAaC,QAAQ,qBAAuBkB,GAGvDb,IACFZ,EAAMK,OAAOC,aAAaC,QAAQ,gBAAkBK,GAGlDG,IACFf,EAAMK,OAAOC,aAAaC,QAAQ,gBAAkBQ,UAIjDvC,OAAO4B,qBC/FD,MAAMuB,UAAsBC,YACzCC,oBACEC,kBAAkBC,MAElBA,KAAKpD,iBAAiB,SAASqB,GAAS+B,KAAKC,MAAMhC,GAAO,KAC1D+B,KAAKX,cAAc,qBAAqBzC,iBAAiB,SAASqB,GAAS+B,KAAKC,MAAMhC,KAGxF6B,MAAM7B,EAAOiC,GAAO,GACdA,GAAQjC,EAAMC,SAAW8B,OAE7BG,iBAAiBH,MAGjBI,YAAW,KACTJ,KAAKK,WACJ,KAIPC,eAAeC,OAAO,oBAAqBX,GCO3CU,eAAeC,OAAO,kBAzBtB,cAA0BX,EACxBE,oBACEU,MAAMC,oBAEN,MAAMC,EAAYC,MAAM5D,UAAU6D,QAAQC,SAErCpE,OAAOqE,kBACVrE,OAAOqE,gBAAkB,IAG3BrE,OAAOqE,gBAAgBC,KAAKL,GAC5BC,MAAM5D,UAAU6D,QAAQG,KAAK,IAAIC,IAAIhB,KAAKiB,cAAc1B,aAAa,SAGvEO,MAAM7B,EAAOiC,GAAO,GACdA,GAAQjC,EAAMC,SAAW8B,OAE7BQ,MAAMP,MAAMhC,EAAOiC,GAEfzD,OAAOqE,gBAAgB1C,OAAS,GAClCuC,MAAM5D,UAAU6D,QAAQM,QAAQzE,OAAOqE,gBAAgBK,WChB7D1E,OAAOsD,kBJyKwB,SAA2BqB,EAAevD,GAEvE,GAAKuD,GAOL,IAAIjE,EAAMQ,MAAK,SAAUC,GACvB,OAAOA,EAAKwD,gBAAkBA,KADhC,CAMA,IAAIxD,EAAO,CACTwD,cAAeA,EACfvD,QAASA,GAAW,IAGtBV,EAAQ,GAAGkE,OAnMb,SAA4BC,GAAO,GAAIC,MAAMC,QAAQF,GAAM,CAAE,IAAK,IAAIG,EAAI,EAAGC,EAAOH,MAAMD,EAAIlD,QAASqD,EAAIH,EAAIlD,OAAQqD,IAAOC,EAAKD,GAAKH,EAAIG,GAAM,OAAOC,EAAe,OAAOH,MAAMI,KAAKL,GAmMtKM,CAAmBzE,GAAQ,CAACS,IAE1Cd,EAnGGL,OAAOoF,uBAAsB,WAElC,QAA6BC,IAAzBvE,EAAoC,CACtCA,EAAuB,CACrBwE,SAAU3C,SAAS4C,KAAKC,MAAMF,SAC9BG,IAAK9C,SAAS4C,KAAKC,MAAMC,IACzBC,KAAM/C,SAAS4C,KAAKC,MAAME,MAI5B,IAAIC,EAAU3F,OACV4F,EAAUD,EAAQC,QAClBC,EAAUF,EAAQE,QAClBC,EAAcH,EAAQG,YAE1BnD,SAAS4C,KAAKC,MAAMF,SAAW,QAC/B3C,SAAS4C,KAAKC,MAAMC,KAAOG,EAC3BjD,SAAS4C,KAAKC,MAAME,MAAQG,EAE5BlC,YAAW,WACT,OAAO3D,OAAOoF,uBAAsB,WAElC,IAAIW,EAAkBD,EAAc9F,OAAO8F,YACvCC,GAAmBH,GAAWE,IAEhCnD,SAAS4C,KAAKC,MAAMC,MAAQG,EAAUG,SAGzC,SAnEe,SAA2B3E,GAEjD,QAAiCiE,IAA7BtE,EAAwC,CAC1C,IAAIiF,IAAyB5E,IAA2C,IAAhCA,EAAQ6E,oBAC5CC,EAAelG,OAAOmG,WAAaxD,SAASyD,gBAAgBC,YAEhE,GAAIL,GAAwBE,EAAe,EAAG,CAC5C,IAAII,EAA2BC,SAASvG,OAAOwG,iBAAiB7D,SAAS4C,MAAMkB,iBAAiB,iBAAkB,IAClH1F,EAA2B4B,SAAS4C,KAAKC,MAAMkB,aAC/C/D,SAAS4C,KAAKC,MAAMkB,aAAeJ,EAA2BJ,EAAe,WAK7Cb,IAAhCxE,IACFA,EAA8B8B,SAAS4C,KAAKC,MAAMmB,SAClDhE,SAAS4C,KAAKC,MAAMmB,SAAW,UA6H/BC,CAAkBxF,GAGhBf,IACFsE,EAAckC,aAAe,SAAUrF,GACF,IAA/BA,EAAMsF,cAAcnF,SAEtBf,EAAiBY,EAAMsF,cAAc,GAAGC,UAG5CpC,EAAcqC,YAAc,SAAUxF,GACD,IAA/BA,EAAMsF,cAAcnF,QAzDX,SAAsBH,EAAOmD,GAC9C,IAAIoC,EAAUvF,EAAMsF,cAAc,GAAGC,QAAUnG,GAE3CI,EAAeQ,EAAMC,UAIrBkD,GAA6C,IAA5BA,EAAcsC,WAAmBF,EAAU,GAX7B,SAAwCpC,GAC3E,QAAOA,GAAgBA,EAAcuC,aAAevC,EAAcsC,WAAatC,EAAcwC,aAezFC,CAA+BzC,IAAkBoC,EAAU,EAHtD1F,EAAeG,GAQxBA,EAAM6F,mBA0CAC,CAAa9F,EAAOmD,IAInBhE,IACHgC,SAASxC,iBAAiB,YAAakB,EAAgBtB,EAAmB,CAAEG,SAAS,QAAUmF,GAC/F1E,GAAwB,UAxC1B4G,QAAQC,MAAM,mHI5KlBxH,OAAO0D,iBJmPuB,SAA0BiB,GACjDA,GAMLjE,EAAQA,EAAM+G,QAAO,SAAUtG,GAC7B,OAAOA,EAAKwD,gBAAkBA,KAG5BtE,IACFsE,EAAckC,aAAe,KAC7BlC,EAAcqC,YAAc,KAExBrG,GAA0C,IAAjBD,EAAMiB,SACjCgB,SAASvC,oBAAoB,YAAaiB,EAAgBtB,EAAmB,CAAEG,SAAS,QAAUmF,GAClG1E,GAAwB,IAIxBN,EA5IuB,WAC3B,QAA6BgF,IAAzBvE,EAAoC,CAEtC,IAAI4G,GAAKnB,SAAS5D,SAAS4C,KAAKC,MAAMC,IAAK,IACvCkC,GAAKpB,SAAS5D,SAAS4C,KAAKC,MAAME,KAAM,IAG5C/C,SAAS4C,KAAKC,MAAMF,SAAWxE,EAAqBwE,SACpD3C,SAAS4C,KAAKC,MAAMC,IAAM3E,EAAqB2E,IAC/C9C,SAAS4C,KAAKC,MAAME,KAAO5E,EAAqB4E,KAGhD1F,OAAO4H,SAASD,EAAGD,GAEnB5G,OAAuBuE,GA+HvBwC,SAhM+BxC,IAA7BtE,IACF4B,SAAS4C,KAAKC,MAAMkB,aAAe3F,EAInCA,OAA2BsE,QAGOA,IAAhCxE,IACF8B,SAAS4C,KAAKC,MAAMmB,SAAW9F,EAI/BA,OAA8BwE,KAgK9BkC,QAAQC,MAAM"}
@@ -10,22 +10,26 @@ module Overlastic::Concerns::OverlayHandling
10
10
  request.variant = :overlay if helpers.current_overlay_name.present?
11
11
  end
12
12
 
13
- def close_overlay(key = :last)
13
+ def close_overlay(key = :last, **options)
14
14
  overlay_name = helpers.overlay_name_from key
15
15
 
16
- render overlay: overlay_name, html: helpers.overlastic_tag(id: helpers.current_overlay_name)
17
- end
16
+ options.filter { |key, _| key.in? self.class._flash_types }.each { |key, value| flash.now[key] = value }
18
17
 
19
- def render(*args, &block)
20
- options = args.last || {}
18
+ if block_given?
19
+ render overlay: overlay_name, html: helpers.overlastic_tag(id: helpers.current_overlay_name), append_turbo_stream: yield
20
+ else
21
+ render overlay: overlay_name, html: helpers.overlastic_tag(id: helpers.current_overlay_name)
22
+ end
23
+ end
21
24
 
25
+ def render(*args, **options, &block)
22
26
  # Force render of overlays without an initiator
23
27
  request.headers["Overlay-Target"] ||= options.delete(:overlay_target)
24
28
  request.headers["Overlay-Type"] ||= options.delete(:overlay_type)
25
29
  request.headers["Overlay-Args"] ||= options.delete(:overlay_args)&.to_json
26
30
 
27
- # Force visit to the desired redirection location
28
- response.headers["Overlay-Visit"] ||= options.delete(:redirect)
31
+ # If renderable content other than HTML is passed we should avoid returning a stream
32
+ avoid_stream = _renderers.excluding(:html).intersection(options.keys).present?
29
33
 
30
34
  # Rendering with an error status should render inside the overlay
31
35
  error = Rack::Utils.status_code(options[:status]).in? 400..499
@@ -43,23 +47,32 @@ module Overlastic::Concerns::OverlayHandling
43
47
  overlay = options.delete :overlay
44
48
  overlay_name = helpers.overlay_name_from(overlay || helpers.current_overlay_name)
45
49
 
46
- if overlay && overlastic_enabled
47
- options[:layout] = false
50
+ if overlastic_enabled
51
+ if overlay
52
+ options[:layout] = false
48
53
 
49
- if block_given? || options[:html]
50
- super turbo_stream: turbo_stream.replace(overlay_name, html: render_to_string(*args, &block))
51
- else
52
- super turbo_stream: turbo_stream.replace(overlay_name, html: helpers.render_overlay { render_to_string(*args, &block) })
53
- end
54
- elsif request.variant.overlay?
55
- if initiator || error || target != "_top"
56
- super turbo_stream: turbo_stream.replace(overlay_name, html: helpers.render_overlay { render_to_string(*args, &block) })
57
- else
58
- request.headers["Turbo-Frame"] = nil
59
- response.headers["Overlay-Visit"] = request.fullpath
54
+ if block_given? || options[:html]
55
+ stream_response = turbo_stream.replace(overlay_name, html: render_to_string(*args, **options, &block))
56
+ else
57
+ stream_response = turbo_stream.replace(overlay_name, html: helpers.render_overlay { render_to_string(*args, **options, &block) })
58
+ end
59
+ elsif request.variant.overlay?
60
+ if initiator || error || target != "_top"
61
+ options[:layout] = false
60
62
 
61
- super
63
+ stream_response = turbo_stream.replace(overlay_name, html: helpers.render_overlay { render_to_string(*args, **options, &block) })
64
+ else
65
+ request.headers["Overlay-Name"] = nil
66
+ end
62
67
  end
68
+ end
69
+
70
+ if stream_response && !avoid_stream
71
+ super turbo_stream: [
72
+ stream_response,
73
+ *options[:append_turbo_stream],
74
+ *(instance_eval(&Overlastic.configuration.append_turbo_stream) if Overlastic.configuration.append_turbo_stream)
75
+ ]
63
76
  else
64
77
  super
65
78
  end
@@ -74,12 +87,10 @@ module Overlastic::Concerns::OverlayHandling
74
87
 
75
88
  if request.variant.overlay?
76
89
  if overlay_name.present?
77
- unless helpers.valid_overlay_name? overlay_name
78
- return render overlay: helpers.current_overlay_name, redirect: location, html: helpers.overlastic_tag(id: helpers.current_overlay_name)
79
- end
90
+ overlay_name = nil unless helpers.valid_overlay_name?(overlay_name)
80
91
 
81
92
  request.variant.delete :overlay
82
- flash.merge! response_options.fetch :flash, {}
93
+ flash.merge! response_options.filter { |key, _| key.in? self.class._flash_types }
83
94
 
84
95
  case Rack::Utils.status_code(response_options.fetch(:status, :created))
85
96
  when 300..399 then response_options[:status] = :created
@@ -8,12 +8,14 @@ module Overlastic::NavigationHelper
8
8
  options = options.stringify_keys
9
9
  options["data"] ||= {}
10
10
 
11
+ options["data"][:turbo_stream] = true
12
+
13
+ overlay_name = options.delete("overlay")
14
+ options["data"][:overlay_name] = overlay_name_from(overlay_name || overlay_name_from_overlastic_action(Overlastic.configuration.default_action))
15
+
11
16
  type = options.delete("overlay_type") || method_type
12
17
  options["data"][:overlay_type] = type if type.present?
13
18
 
14
- action = options.delete("overlay_action") || Overlastic.configuration.default_action
15
- options["data"][:turbo_frame] = turbo_frame_from_overlastic_action(action)
16
-
17
19
  target = options.delete("overlay_target")
18
20
  options["data"][:overlay_target] = target if target.present?
19
21
 
@@ -26,12 +28,14 @@ module Overlastic::NavigationHelper
26
28
  html_options = html_options.stringify_keys
27
29
  html_options["data"] ||= {}
28
30
 
31
+ html_options["data"][:turbo_stream] = true
32
+
33
+ overlay_name = html_options.delete("overlay")
34
+ html_options["data"][:overlay_name] = overlay_name_from(overlay_name || overlay_name_from_overlastic_action(Overlastic.configuration.default_action))
35
+
29
36
  type = html_options.delete("overlay_type") || method_type
30
37
  html_options["data"][:overlay_type] = type if type.present?
31
38
 
32
- action = html_options.delete("overlay_action") || Overlastic.configuration.default_action
33
- html_options["data"][:turbo_frame] = turbo_frame_from_overlastic_action(action)
34
-
35
39
  target = html_options.delete("overlay_target")
36
40
  html_options["data"][:overlay_target] = target if target.present?
37
41
 
@@ -48,7 +52,7 @@ module Overlastic::NavigationHelper
48
52
 
49
53
  private
50
54
 
51
- def turbo_frame_from_overlastic_action(action)
55
+ def overlay_name_from_overlastic_action(action)
52
56
  case action
53
57
  when :stack
54
58
  overlay_name_from :next
@@ -5,20 +5,18 @@ module Overlastic::OverlaysHelper
5
5
  target = request.headers["Overlay-Target"] || Overlastic.configuration.default_target
6
6
  args = request.headers["Overlay-Args"]
7
7
 
8
- turbo_frame_tag current_overlay_name || id, src: request.url, cancel: true, data: { overlay_type: type, overlay_target: target, overlay_args: args } do
8
+ tag.overlastic id: current_overlay_name || id, src: request.url, data: { overlay_type: type, overlay_target: target, overlay_args: args } do
9
9
  yield
10
10
 
11
- concat turbo_frame_tag(overlay_name_from(:next), data: { overlay_target: Overlastic.configuration.default_target })
11
+ concat tag.overlastic(id: overlay_name_from(:next), data: { overlay_target: Overlastic.configuration.default_target })
12
12
  end
13
13
  else
14
- turbo_frame_tag id, data: { overlay_target: Overlastic.configuration.default_target }
14
+ tag.overlastic id: id, data: { overlay_target: Overlastic.configuration.default_target }
15
15
  end
16
16
  end
17
17
 
18
18
  def current_overlay_name
19
- return unless request.headers["Turbo-Frame"].to_s.starts_with?("overlay")
20
-
21
- request.headers["Turbo-Frame"].to_sym
19
+ request.headers["Overlay-Name"]&.to_sym
22
20
  end
23
21
 
24
22
  def overlay_name_from(key)
@@ -1,17 +1,6 @@
1
- // Save the clicked overlay link element for use down the line.
1
+ // Save the clicked element for use down the line.
2
2
  addEventListener("click", event => {
3
- window._overlasticAnchor = event.target.closest("a[data-turbo-frame^=overlay]")
4
- }, true)
5
-
6
- // In order to respect frame behavior, overlay stream responses replace whole frames and
7
- // come with the correct src. This triggers the frame controller to attempt an eager load.
8
- // We don't want that for overlays, so we cancel those requests.
9
- addEventListener("turbo:before-fetch-request", event => {
10
- if (!event.target.hasAttribute("cancel")) return
11
-
12
- event.preventDefault()
13
-
14
- event.target.removeAttribute("cancel")
3
+ window._overlasticAnchor = event.target
15
4
  }, true)
16
5
 
17
6
  // Allow progressive enhancement by telling the server if a request is handled by Turbo.
@@ -20,45 +9,75 @@ addEventListener("turbo:before-fetch-request", event => {
20
9
  })
21
10
 
22
11
  // When an overlay anchor is clicked,
23
- // send its type, target and args along with the frame request.
12
+ // send its type, target and args along with the visit request.
24
13
  addEventListener("turbo:before-fetch-request", event => {
25
- if (!window._overlasticAnchor) return
26
-
27
- const anchor = window._overlasticAnchor
14
+ const anchor = event.target
15
+ const name = anchor?.dataset?.overlayName
28
16
  const type = anchor?.dataset?.overlayType
29
17
  const target = anchor?.dataset?.overlayTarget
30
18
  const args = anchor?.dataset?.overlayArgs
31
19
 
32
- event.detail.fetchOptions.headers["Overlay-Initiator"] = "1"
20
+ if (name?.startsWith("overlay")) {
21
+ event.detail.fetchOptions.headers["Overlay-Initiator"] = "1"
22
+ event.detail.fetchOptions.headers["Overlay-Name"] = name
33
23
 
34
- if (type) {
35
- event.detail.fetchOptions.headers["Overlay-Type"] = type
36
- }
24
+ if (type) {
25
+ event.detail.fetchOptions.headers["Overlay-Type"] = type
26
+ }
37
27
 
38
- if (target) {
39
- event.detail.fetchOptions.headers["Overlay-Target"] = target
40
- }
28
+ if (target) {
29
+ event.detail.fetchOptions.headers["Overlay-Target"] = target
30
+ }
41
31
 
42
- if (args) {
43
- event.detail.fetchOptions.headers["Overlay-Args"] = args
32
+ if (args) {
33
+ event.detail.fetchOptions.headers["Overlay-Args"] = args
34
+ }
44
35
  }
36
+ })
37
+
38
+ // When the redirect script triggers a fetch,
39
+ // send the current overlay's target along with the visit request.
40
+ addEventListener("turbo:before-fetch-request", event => {
41
+ const script = document.querySelector("script[overlay]")
42
+
43
+ if (script) {
44
+ const overlay = document.querySelector(`overlastic[id=${script.getAttribute("overlay")}]`)
45
+
46
+ if (overlay) {
47
+ const name = overlay.id
48
+ const target = overlay.dataset.overlayTarget
49
+ const type = overlay.dataset?.overlayType
50
+ const args = overlay.dataset?.overlayArgs
51
+
52
+ event.detail.fetchOptions.headers["Overlay-Name"] = name
53
+ event.detail.fetchOptions.headers["Overlay-Target"] = target
54
+ event.detail.fetchOptions.headers["Overlay-Initiator"] = "1"
55
+
56
+ if (type) {
57
+ event.detail.fetchOptions.headers["Overlay-Type"] = type
58
+ }
45
59
 
46
- delete window._overlasticTarget
60
+ if (args) {
61
+ event.detail.fetchOptions.headers["Overlay-Args"] = args
62
+ }
63
+ }
64
+ }
47
65
  })
48
66
 
49
67
  // When any other element triggers a fetch,
50
- // send the current overlay's target along with the frame request.
68
+ // send the current overlay's target along with the visit request.
51
69
  addEventListener("turbo:before-fetch-request", event => {
52
- if (window._overlasticAnchor) return
53
-
54
- const frame = event.target.closest("turbo-frame[id^=overlay]")
70
+ const anchor = window._overlasticAnchor
71
+ const overlay = anchor.closest("overlastic")
55
72
 
56
- if (frame) {
57
- const target = frame.dataset.overlayTarget
58
- const initiator = frame.dataset?.overlayInitiator
59
- const type = frame.dataset?.overlayType
60
- const args = frame.dataset?.overlayArgs
73
+ if (overlay && !anchor.dataset.overlay && !anchor.dataset.overlayName) {
74
+ const name = overlay.id
75
+ const target = overlay.dataset.overlayTarget
76
+ const initiator = overlay.dataset?.overlayInitiator
77
+ const type = overlay.dataset?.overlayType
78
+ const args = overlay.dataset?.overlayArgs
61
79
 
80
+ event.detail.fetchOptions.headers["Overlay-Name"] = name
62
81
  event.detail.fetchOptions.headers["Overlay-Target"] = target
63
82
 
64
83
  if (initiator) {
@@ -73,17 +92,6 @@ addEventListener("turbo:before-fetch-request", event => {
73
92
  event.detail.fetchOptions.headers["Overlay-Args"] = args
74
93
  }
75
94
  }
76
- })
77
-
78
- // Handle frame-to-visit promotions when the server asks for it.
79
- addEventListener("turbo:before-fetch-response", async event => {
80
- const fetchResponse = event.detail.fetchResponse
81
- const visit = fetchResponse.response.headers.get("Overlay-Visit")
82
-
83
- if (!visit) return
84
-
85
- const responseHTML = await fetchResponse.responseHTML
86
- const { redirected, statusCode } = fetchResponse
87
95
 
88
- return Turbo.session.visit(visit, { shouldCacheSnapshot: false, response: { redirected, statusCode, responseHTML } })
96
+ delete window._overlasticAnchor
89
97
  })
@@ -11,7 +11,7 @@ class PaneElement extends DialogElement {
11
11
  }
12
12
 
13
13
  window.modalVisitStack.push(lastVisit)
14
- Turbo.navigator.history.push(new URL(this.parentElement.src))
14
+ Turbo.navigator.history.push(new URL(this.parentElement.getAttribute("src")))
15
15
  }
16
16
 
17
17
  close(event, self = false) {
@@ -1,10 +1,6 @@
1
1
  <%= turbo_stream.append_all "head" do %>
2
- <%= javascript_tag nonce: true do %>
3
- frame = document.querySelector("turbo-frame[id=<%= escape_javascript overlay %>]")
4
-
5
- frame.dataset.overlayInitiator = "1"
6
- frame.src = "<%= escape_javascript location %>"
7
-
2
+ <%= javascript_tag nonce: true, overlay: overlay do %>
3
+ window.Turbo.visit("<%= escape_javascript location %>")
8
4
  document.currentScript.remove()
9
5
  <% end %>
10
6
  <% end %>
@@ -23,5 +23,13 @@ module Overlastic
23
23
  public_send :"#{overlay_type}_overlay_view_path=", "overlastic/inline/#{overlay_type}"
24
24
  end
25
25
  end
26
+
27
+ def append_turbo_stream(&block)
28
+ if block_given?
29
+ @append_turbo_stream = block
30
+ else
31
+ @append_turbo_stream
32
+ end
33
+ end
26
34
  end
27
35
  end
@@ -1,3 +1,3 @@
1
1
  module Overlastic
2
- VERSION = "0.6.1"
2
+ VERSION = "0.7.0"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: overlastic
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.1
4
+ version: 0.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Martin Zamuner