overlastic 0.8.1 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml 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