overlastic 0.8.1 → 0.9.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: 31c1e66d88f867bfbee971acda5660a8763a6aeeb064f17847087354bae8dac7
4
- data.tar.gz: 31ed342bb24afe3fe85f4ecb039c3b587a79b00bd89cd850d61d1ba4f86c19fe
3
+ metadata.gz: e96bc71c763fd39cbc4b0ee2a07019e30844548150f6ed631cb0620841b5eda1
4
+ data.tar.gz: e69237d7b05f3fca7725cf24d23e4ef995359d3f3a52dd1dff942c341afe1c47
5
5
  SHA512:
6
- metadata.gz: 216fd42cc4b04429dcba56428800c72f2ff05751cd674a7f8398cb73b01d7b6a0fc14d261380a52630a3d03d341736c6002e3bce3eb8b0531bc6c179a5a9e9af
7
- data.tar.gz: 201f037238840e7947f6a1510329d804eb774f97ce21b243b48123cf11001785eb7cc5d28de63aee6f1b25ea36b07646a43ce735b907e10a6fa5a33c5dc879e8
6
+ metadata.gz: 6c3ebd9884690c569505c86b47d4b6e05c99ec62460c7645151a392c23ce7f44a7cec50fdd5b49d939d88876e04f65691c8a17528ce4a88d25fbddca9688015e
7
+ data.tar.gz: 60aecc32d39d580e76f574720e6a0bdb9e1357b997d66d83c350f2a2d87492c821e4cbb8ebd3c61bb199101cf84f431ca4246fdfc1cf34acd978e21754df952e
data/README.md CHANGED
@@ -133,6 +133,39 @@ redirect_to article_url(@article), overlay: :previous, status: :see_other
133
133
  ```
134
134
  </details>
135
135
 
136
+ <details>
137
+ <summary>Attaching to lifecycle events</summary><br>
138
+
139
+ If you want to add custom behavior every time an overlay is removed or attached to the DOM, you can listen to their lifecycle events:
140
+
141
+ - `overlastic:connected`
142
+ - `overlastic:disconnected`
143
+
144
+ They target the first element in your view to make it easy to add listeners using libraries like Stimulus. You could, for example, have something like this:
145
+
146
+ ```html
147
+ <!-- app/views/overlay/_dialog.html.erb -->
148
+
149
+ <div data-controller="overlay" data-action="overlastic:disconnect->overlay#close">
150
+ ...
151
+ </div>
152
+ ```
153
+
154
+ The `overlastic:disconnect` event can be paused and resumed, which allows you to run lengthy functions, like animations, before being closed or replaced by another overlay:
155
+
156
+ ```js
157
+ close(event) {
158
+ event.preventDefault()
159
+
160
+ this.leave().then(() => {
161
+ event.detail.resume()
162
+ })
163
+ }
164
+ ```
165
+
166
+ If there are many overlays being closed at the same time, all of them will be dispatched an `overlastic:disconnect` event. This is great to have independent animations for each of them.
167
+ </details>
168
+
136
169
  ### Advanced features
137
170
 
138
171
  <details>
@@ -284,6 +284,40 @@ addEventListener("turbo:before-fetch-request", (event => {
284
284
  delete window._overlasticInitiator;
285
285
  }));
286
286
 
287
+ Turbo.StreamActions["replaceOverlay"] = function() {
288
+ let overlaysReadyToDisconnect = [];
289
+ let callsToResume = 0;
290
+ const oldOverlay = this.targetElements[0];
291
+ const overlayName = oldOverlay.id;
292
+ const renderNewOverlay = () => {
293
+ callsToResume++;
294
+ if (callsToResume >= overlaysReadyToDisconnect.filter((status => status === false)).length) {
295
+ Turbo.StreamActions["replace"].bind(this)();
296
+ const newOverlay = document.getElementById(overlayName);
297
+ const connectTarget = newOverlay.firstElementChild || newOverlay;
298
+ const connectEvent = new Event("overlastic:connect", {
299
+ bubbles: true,
300
+ cancelable: false
301
+ });
302
+ connectTarget.dispatchEvent(connectEvent);
303
+ }
304
+ };
305
+ overlaysReadyToDisconnect = [ oldOverlay, ...oldOverlay.querySelectorAll("overlastic") ].map((element => {
306
+ const disconnectTarget = element.firstElementChild || element;
307
+ const disconnectEvent = new CustomEvent("overlastic:disconnect", {
308
+ bubbles: true,
309
+ cancelable: true,
310
+ detail: {
311
+ resume: renderNewOverlay
312
+ }
313
+ });
314
+ return disconnectTarget.dispatchEvent(disconnectEvent);
315
+ }));
316
+ if (overlaysReadyToDisconnect.every((status => status === true))) {
317
+ renderNewOverlay();
318
+ }
319
+ };
320
+
287
321
  class DialogElement extends HTMLElement {
288
322
  connectedCallback() {
289
323
  disableBodyScroll(this);
@@ -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=[],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._overlasticInitiator=e.target}),!0),addEventListener("click",(e=>{const t=window._overlasticInitiator?.closest("a[data-overlay-name]");t&&t.removeAttribute("target")}),!0),addEventListener("turbo:before-fetch-request",(e=>{e.detail.fetchOptions.headers["Overlay-Enabled"]="1"})),addEventListener("turbo:before-fetch-request",(e=>{const t=window._overlasticInitiator?.closest("a[data-overlay-name]"),o=t?.dataset?.overlayName,n=t?.dataset?.overlayType,a=t?.dataset?.overlayTarget,i=t?.dataset?.overlayArgs;t&&(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._overlasticInitiator?.closest("a, form"),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._overlasticInitiator}));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.")};
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=[],i=!1,a=-1,r=void 0,l=void 0,s=void 0,d=function(e){return n.some((function(t){return!(!t.options.allowTouchMove||!t.options.allowTouchMove(e))}))},c=function(e){var t=e||window.event;return!!d(t.target)||(t.touches.length>1||(t.preventDefault&&t.preventDefault(),!1))};addEventListener("click",(e=>{window._overlasticInitiator=e.target}),!0),addEventListener("click",(e=>{const t=window._overlasticInitiator?.closest("a[data-overlay-name]");t&&t.removeAttribute("target")}),!0),addEventListener("turbo:before-fetch-request",(e=>{e.detail.fetchOptions.headers["Overlay-Enabled"]="1"})),addEventListener("turbo:before-fetch-request",(e=>{const t=window._overlasticInitiator?.closest("a[data-overlay-name]"),o=t?.dataset?.overlayName,n=t?.dataset?.overlayType,i=t?.dataset?.overlayTarget,a=t?.dataset?.overlayArgs;t&&(e.detail.fetchOptions.headers["Overlay-Initiator"]="1",e.detail.fetchOptions.headers["Overlay-Name"]=o,n&&(e.detail.fetchOptions.headers["Overlay-Type"]=n),i&&(e.detail.fetchOptions.headers["Overlay-Target"]=i),a&&(e.detail.fetchOptions.headers["Overlay-Args"]=a))})),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,i=o.dataset?.overlayType,a=o.dataset?.overlayArgs;e.detail.fetchOptions.headers["Overlay-Name"]=t,e.detail.fetchOptions.headers["Overlay-Target"]=n,e.detail.fetchOptions.headers["Overlay-Initiator"]="1",i&&(e.detail.fetchOptions.headers["Overlay-Type"]=i),a&&(e.detail.fetchOptions.headers["Overlay-Args"]=a)}}})),addEventListener("turbo:before-fetch-request",(e=>{const t=window._overlasticInitiator?.closest("a, form"),o=t?.closest("overlastic");if(o&&!t.dataset.overlay&&!t.dataset.overlayName){const t=o.id,n=o.dataset.overlayTarget,i=o.dataset?.overlayInitiator,a=o.dataset?.overlayType,r=o.dataset?.overlayArgs;e.detail.fetchOptions.headers["Overlay-Name"]=t,e.detail.fetchOptions.headers["Overlay-Target"]=n,i&&(e.detail.fetchOptions.headers["Overlay-Initiator"]=i),a&&(e.detail.fetchOptions.headers["Overlay-Type"]=a),r&&(e.detail.fetchOptions.headers["Overlay-Args"]=r)}delete window._overlasticInitiator})),Turbo.StreamActions.replaceOverlay=function(){let e=[],t=0;const o=this.targetElements[0],n=o.id,i=()=>{if(t++,t>=e.filter((e=>!1===e)).length){Turbo.StreamActions.replace.bind(this)();const e=document.getElementById(n),t=e.firstElementChild||e,o=new Event("overlastic:connect",{bubbles:!0,cancelable:!1});t.dispatchEvent(o)}};e=[o,...o.querySelectorAll("overlastic")].map((e=>{const t=e.firstElementChild||e,o=new CustomEvent("overlastic:disconnect",{bubbles:!0,cancelable:!0,detail:{resume:i}});return t.dispatchEvent(o)})),e.every((e=>!0===e))&&i()};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===l){l={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===s){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);s=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&&(a=e.targetTouches[0].clientY)},t.ontouchmove=function(e){1===e.targetTouches.length&&function(e,t){var o=e.targetTouches[0].clientY-a;!d(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)},i||(document.addEventListener("touchmove",c,e?{passive:!1}:void 0),i=!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,i&&0===n.length&&(document.removeEventListener("touchmove",c,e?{passive:!1}:void 0),i=!1)),o?function(){if(void 0!==l){var e=-parseInt(document.body.style.top,10),t=-parseInt(document.body.style.left,10);document.body.style.position=l.position,document.body.style.top=l.top,document.body.style.left=l.left,window.scrollTo(t,e),l=void 0}}():(void 0!==s&&(document.body.style.paddingRight=s,s=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 element for use down the line.\naddEventListener(\"click\", event => {\n window._overlasticInitiator = event.target\n}, true)\n\n// Overlay anchors come with target _blank to serve as fallback in case JS is not enabled.\naddEventListener(\"click\", _event => {\n const anchor = window._overlasticInitiator?.closest(\"a[data-overlay-name]\")\n\n if (anchor) {\n anchor.removeAttribute(\"target\")\n }\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 = window._overlasticInitiator?.closest(\"a[data-overlay-name]\")\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 (anchor) {\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 initiator = window._overlasticInitiator?.closest(\"a, form\")\n const overlay = initiator?.closest(\"overlastic\")\n\n if (overlay && !initiator.dataset.overlay && !initiator.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._overlasticInitiator\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","_overlasticInitiator","_event","anchor","closest","removeAttribute","detail","fetchOptions","headers","name","dataset","overlayName","type","overlayType","overlayTarget","args","overlayArgs","script","document","querySelector","overlay","getAttribute","id","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":"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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/streamAction.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._overlasticInitiator = event.target\n}, true)\n\n// Overlay anchors come with target _blank to serve as fallback in case JS is not enabled.\naddEventListener(\"click\", _event => {\n const anchor = window._overlasticInitiator?.closest(\"a[data-overlay-name]\")\n\n if (anchor) {\n anchor.removeAttribute(\"target\")\n }\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 = window._overlasticInitiator?.closest(\"a[data-overlay-name]\")\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 (anchor) {\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 initiator = window._overlasticInitiator?.closest(\"a, form\")\n const overlay = initiator?.closest(\"overlastic\")\n\n if (overlay && !initiator.dataset.overlay && !initiator.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._overlasticInitiator\n})\n","// Custom Stream action that allows for finer control of the overlay lifecycle.\n//\n// Lifecycle events:\n// - overlastic:disconnect right before removing an overlay from the DOM\n// - overlastic:connect right after attaching an overlay to the DOM\n//\n// Both events target the firstElementChild of the overlastic tag to allow for\n// a cleaner listening approach in libraries like Stimulus or Alpine.\n//\n// The disconnect event is dispatched once for every overlay that will be removed.\n// They can be paused and resumed. The new overlay won't be attached until all events\n// have been resumed.\nTurbo.StreamActions[\"replaceOverlay\"] = function() {\n let overlaysReadyToDisconnect = []\n let callsToResume = 0\n\n const oldOverlay = this.targetElements[0]\n const overlayName = oldOverlay.id\n const renderNewOverlay = () => {\n callsToResume++\n\n if (callsToResume >= overlaysReadyToDisconnect.filter(status => status === false).length) {\n Turbo.StreamActions[\"replace\"].bind(this)()\n\n const newOverlay = document.getElementById(overlayName)\n const connectTarget = newOverlay.firstElementChild || newOverlay\n const connectEvent = new Event(\"overlastic:connect\", { bubbles: true, cancelable: false })\n\n connectTarget.dispatchEvent(connectEvent)\n }\n }\n\n overlaysReadyToDisconnect = [oldOverlay, ...oldOverlay.querySelectorAll(\"overlastic\")].map(element => {\n const disconnectTarget = element.firstElementChild || element\n const disconnectEvent =\n new CustomEvent(\"overlastic:disconnect\", { bubbles: true, cancelable: true, detail: { resume: renderNewOverlay } })\n\n return disconnectTarget.dispatchEvent(disconnectEvent)\n })\n\n if (overlaysReadyToDisconnect.every(status => status === true)) {\n renderNewOverlay()\n }\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 \"./streamAction\"\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","_overlasticInitiator","_event","anchor","closest","removeAttribute","detail","fetchOptions","headers","name","dataset","overlayName","type","overlayType","overlayTarget","args","overlayArgs","script","document","querySelector","overlay","getAttribute","id","initiator","overlayInitiator","Turbo","StreamActions","overlaysReadyToDisconnect","callsToResume","oldOverlay","this","targetElements","renderNewOverlay","filter","status","bind","newOverlay","getElementById","connectTarget","firstElementChild","connectEvent","Event","bubbles","cancelable","dispatchEvent","querySelectorAll","map","element","disconnectTarget","disconnectEvent","CustomEvent","resume","every","DialogElement","HTMLElement","[object Object]","disableBodyScroll","close","self","enableBodyScroll","setTimeout","remove","customElements","define","super","connectedCallback","lastVisit","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","y","x","scrollTo","restorePositionSetting"],"mappings":"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"}
@@ -47,20 +47,24 @@ module Overlastic::Concerns::OverlayHandling
47
47
  overlay = options.delete :overlay
48
48
  overlay_name = helpers.overlay_name_from(overlay || helpers.current_overlay_name)
49
49
 
50
+ if overlay.present?
51
+ request.headers["Overlay-Name"] = overlay_name
52
+ end
53
+
50
54
  if overlastic_enabled
51
55
  if overlay
52
56
  options[:layout] = false
53
57
 
54
58
  if block_given? || options[:html]
55
- stream_response = turbo_stream.replace(overlay_name, html: render_to_string(*args, **options, &block))
59
+ stream_response = turbo_stream.replace_overlay(overlay_name, html: render_to_string(*args, **options, &block))
56
60
  else
57
- stream_response = turbo_stream.replace(overlay_name, html: helpers.render_overlay { render_to_string(*args, **options, &block) })
61
+ stream_response = turbo_stream.replace_overlay(overlay_name, html: helpers.render_overlay { render_to_string(*args, **options, &block) })
58
62
  end
59
63
  elsif request.variant.overlay?
60
64
  if initiator || error || target != "_top"
61
65
  options[:layout] = false
62
66
 
63
- stream_response = turbo_stream.replace(overlay_name, html: helpers.render_overlay { render_to_string(*args, **options, &block) })
67
+ stream_response = turbo_stream.replace_overlay(overlay_name, html: helpers.render_overlay { render_to_string(*args, **options, &block) })
64
68
  else
65
69
  request.headers["Overlay-Name"] = nil
66
70
  request.variant.delete :overlay
@@ -0,0 +1,7 @@
1
+ module Overlastic::StreamsHelper
2
+ def replace_overlay(target, content = nil, **rendering, &block)
3
+ action :replaceOverlay, target, content, **rendering, &block
4
+ end
5
+ end
6
+
7
+ Turbo::Streams::TagBuilder.prepend(Overlastic::StreamsHelper)
@@ -14,7 +14,7 @@ addEventListener("click", _event => {
14
14
 
15
15
  // Allow progressive enhancement by telling the server if a request is handled by Turbo.
16
16
  addEventListener("turbo:before-fetch-request", event => {
17
- event.detail.fetchOptions.headers["Overlay-Enabled"] = "1"
17
+ event.detail.fetchOptions.headers["Overlay-Enabled"] = "1"
18
18
  })
19
19
 
20
20
  // When an overlay anchor is clicked,
@@ -1,6 +1,7 @@
1
1
  import { disableBodyScroll, enableBodyScroll } from "body-scroll-lock"
2
2
 
3
3
  import "./clickInterceptor"
4
+ import "./streamAction"
4
5
  import "./dialogElement"
5
6
  import "./paneElement"
6
7
 
@@ -0,0 +1,44 @@
1
+ // Custom Stream action that allows for finer control of the overlay lifecycle.
2
+ //
3
+ // Lifecycle events:
4
+ // - overlastic:disconnect right before removing an overlay from the DOM
5
+ // - overlastic:connect right after attaching an overlay to the DOM
6
+ //
7
+ // Both events target the firstElementChild of the overlastic tag to allow for
8
+ // a cleaner listening approach in libraries like Stimulus or Alpine.
9
+ //
10
+ // The disconnect event is dispatched once for every overlay that will be removed.
11
+ // They can be paused and resumed. The new overlay won't be attached until all events
12
+ // have been resumed.
13
+ Turbo.StreamActions["replaceOverlay"] = function() {
14
+ let overlaysReadyToDisconnect = []
15
+ let callsToResume = 0
16
+
17
+ const oldOverlay = this.targetElements[0]
18
+ const overlayName = oldOverlay.id
19
+ const renderNewOverlay = () => {
20
+ callsToResume++
21
+
22
+ if (callsToResume >= overlaysReadyToDisconnect.filter(status => status === false).length) {
23
+ Turbo.StreamActions["replace"].bind(this)()
24
+
25
+ const newOverlay = document.getElementById(overlayName)
26
+ const connectTarget = newOverlay.firstElementChild || newOverlay
27
+ const connectEvent = new Event("overlastic:connect", { bubbles: true, cancelable: false })
28
+
29
+ connectTarget.dispatchEvent(connectEvent)
30
+ }
31
+ }
32
+
33
+ overlaysReadyToDisconnect = [oldOverlay, ...oldOverlay.querySelectorAll("overlastic")].map(element => {
34
+ const disconnectTarget = element.firstElementChild || element
35
+ const disconnectEvent =
36
+ new CustomEvent("overlastic:disconnect", { bubbles: true, cancelable: true, detail: { resume: renderNewOverlay } })
37
+
38
+ return disconnectTarget.dispatchEvent(disconnectEvent)
39
+ })
40
+
41
+ if (overlaysReadyToDisconnect.every(status => status === true)) {
42
+ renderNewOverlay()
43
+ }
44
+ }
@@ -1,3 +1,3 @@
1
1
  module Overlastic
2
- VERSION = "0.8.1"
2
+ VERSION = "0.9.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: overlastic
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.1
4
+ version: 0.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Martin Zamuner
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-09-24 00:00:00.000000000 Z
11
+ date: 2022-09-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: actionpack
@@ -67,10 +67,12 @@ files:
67
67
  - app/controllers/overlastic/concerns/overlay_handling.rb
68
68
  - app/helpers/overlastic/navigation_helper.rb
69
69
  - app/helpers/overlastic/overlays_helper.rb
70
+ - app/helpers/overlastic/streams_helper.rb
70
71
  - app/javascript/overlastic/clickInterceptor.js
71
72
  - app/javascript/overlastic/dialogElement.js
72
73
  - app/javascript/overlastic/index.js
73
74
  - app/javascript/overlastic/paneElement.js
75
+ - app/javascript/overlastic/streamAction.js
74
76
  - app/views/overlastic/inline/_dialog.html.erb
75
77
  - app/views/overlastic/inline/_pane.html.erb
76
78
  - app/views/overlastic/streams/redirect.turbo_stream.erb