overlastic 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +91 -0
- data/Rakefile +15 -0
- data/app/assets/javascripts/overlastic.js +263 -0
- data/app/assets/javascripts/overlastic.min.js +2 -0
- data/app/assets/javascripts/overlastic.min.js.map +1 -0
- data/app/controllers/overlastic/concerns/overlay_handling.rb +21 -0
- data/app/helpers/overlastic/navigation_helper.rb +55 -0
- data/app/helpers/overlastic/overlays_helper.rb +27 -0
- data/app/javascript/overlastic/clickInterceptor.js +21 -0
- data/app/javascript/overlastic/dialogElement.js +21 -0
- data/app/javascript/overlastic/index.js +8 -0
- data/app/javascript/overlastic/paneElement.js +28 -0
- data/app/views/shared/overlays/_dialog.html.erb +28 -0
- data/app/views/shared/overlays/_pane.html.erb +22 -0
- data/app/views/shared/overlays/tailwind/_dialog.html.erb +28 -0
- data/app/views/shared/overlays/tailwind/_pane.html.erb +22 -0
- data/lib/install/overlastic_with_importmap.rb +8 -0
- data/lib/install/overlastic_with_node.rb +5 -0
- data/lib/overlastic/configuration.rb +26 -0
- data/lib/overlastic/engine.rb +28 -0
- data/lib/overlastic/version.rb +3 -0
- data/lib/overlastic.rb +16 -0
- data/lib/tasks/overlastic_tasks.rake +26 -0
- metadata +108 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: e71d0d0cb84a1e1576f09f7e7329ceaf6601dd46cc2045caba2e2aec3ee4f5ba
|
4
|
+
data.tar.gz: fa2a39ad530363af3d3d1b9b04a07f95049d7865774d1684f8e50ac2aa88d9ec
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: c136cb0313643c9fa6c15e73c93e2ad0725920f10548ef848ae784a2418dcefb971d25b45bf393bb2c63e2ca71455e6c7dc24c2f54c6187e23ff3fd3934888e9
|
7
|
+
data.tar.gz: d906bc365ffa890bd4543700cccd7eb200accbdea7086fb8701161cf6239608ac7633ec874794ff8bf7068ac75bd58f2f506414f34ae36ddf3c7389b88758d73
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2022 Martin Zamuner
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,91 @@
|
|
1
|
+
# Overlastic
|
2
|
+
|
3
|
+
Load any page inside an overlay (dialog modal, slide-out pane, or whatever else floats your boat). As easy as replacing `link_to` with `link_to_dialog`.
|
4
|
+
|
5
|
+
|
6
|
+
## Installation
|
7
|
+
|
8
|
+
This gem requires a modern Rails application running [turbo-rails](https://github.com/hotwired/turbo-rails). It supports both import map and node setups.
|
9
|
+
|
10
|
+
1. Add the `overlastic` gem to your Gemfile: `gem "overlastic"`
|
11
|
+
2. Run `./bin/bundle install`
|
12
|
+
3. Run `./bin/rails overlastic:install`
|
13
|
+
|
14
|
+
|
15
|
+
## Usage
|
16
|
+
|
17
|
+
Most of the time you'll just need to replace a `link_to` with one of the overlay helpers:
|
18
|
+
|
19
|
+
```erb
|
20
|
+
<%= link_to_dialog "Open dialog", edit_article_path %>
|
21
|
+
<%= link_to_pane "Open slide-out pane", edit_article_path %>
|
22
|
+
<%= link_to_overlay "Open default overlay type", edit_article_path %>
|
23
|
+
<%= link_to_overlay "Open dialog", edit_article_path, overlay_type: :dialog %>
|
24
|
+
```
|
25
|
+
|
26
|
+
They work just as `link_to` and accept the same options. You can also pass locals to the overlay view:
|
27
|
+
|
28
|
+
```erb
|
29
|
+
<%= link_to_dialog "Open dialog", edit_article_path, overlay_args: { title: "Dialog title" } %>
|
30
|
+
```
|
31
|
+
|
32
|
+
By default, overlays stack on top of each other. You can instead replace the last one or the whole stack:
|
33
|
+
|
34
|
+
```erb
|
35
|
+
<%= link_to_dialog "Open dialog", edit_article_path, overlay_action: :replace_last %>
|
36
|
+
<%= link_to_dialog "Open dialog", edit_article_path, overlay_action: :replace_all %>
|
37
|
+
```
|
38
|
+
|
39
|
+
Sometimes, you may want to alter the content depending on whether it's inside an overlay or not. Overlastic defines a new `:overlay` request variant that you can use to create custom partials like `_form.html+overlay.erb` or inside a controller like so:
|
40
|
+
|
41
|
+
```rb
|
42
|
+
respond_to do |format|
|
43
|
+
format.html.overlay { render :custom_view }
|
44
|
+
format.html
|
45
|
+
end
|
46
|
+
```
|
47
|
+
|
48
|
+
|
49
|
+
## Configuration
|
50
|
+
|
51
|
+
```rb
|
52
|
+
# config/initializers/overlastic.rb
|
53
|
+
|
54
|
+
Overlastic.configure do |config|
|
55
|
+
config.overlay_types = %i[dialog pane]
|
56
|
+
config.default_overlay = :dialog
|
57
|
+
config.default_action = :stack
|
58
|
+
|
59
|
+
# You can define a custom partial for each overlay type
|
60
|
+
config.dialog_overlay_view_path = "shared/overlays/dialog"
|
61
|
+
config.dialog_overlay_view_path = "shared/overlays/pane"
|
62
|
+
end
|
63
|
+
```
|
64
|
+
|
65
|
+
## Development
|
66
|
+
|
67
|
+
<details>
|
68
|
+
<summary>Roadmap</summary><br>
|
69
|
+
|
70
|
+
- Generator to allow easy customization of the overlay views
|
71
|
+
- Handle 4xx responses (p.e. validation errors) when submitting forms inside an overlay
|
72
|
+
</details>
|
73
|
+
|
74
|
+
<details>
|
75
|
+
<summary>Running the demo application</summary><br>
|
76
|
+
|
77
|
+
- First you need to install dependencies with `bundle && yarn && yarn build`
|
78
|
+
- Then you need to setup the DB with `./bin/rails db:migrate`
|
79
|
+
- Lastly you can run the demo app with `./bin/rails server --port 3000`
|
80
|
+
</details>
|
81
|
+
|
82
|
+
<details>
|
83
|
+
<summary>Running the tests</summary><br>
|
84
|
+
|
85
|
+
- You can run the whole suite with `./bin/test`
|
86
|
+
</details>
|
87
|
+
|
88
|
+
|
89
|
+
## License
|
90
|
+
|
91
|
+
Overlastic is released under the [MIT License](https://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
require "bundler/setup"
|
2
|
+
require "bundler/gem_tasks"
|
3
|
+
require "rake/testtask"
|
4
|
+
|
5
|
+
APP_RAKEFILE = File.expand_path("test/dummy/Rakefile", __dir__)
|
6
|
+
load "rails/tasks/engine.rake"
|
7
|
+
load "rails/tasks/statistics.rake"
|
8
|
+
|
9
|
+
Rake::TestTask.new do |test|
|
10
|
+
test.libs << "test"
|
11
|
+
test.test_files = FileList["test/**/*_test.rb"]
|
12
|
+
test.warning = false
|
13
|
+
end
|
14
|
+
|
15
|
+
task default: :test
|
@@ -0,0 +1,263 @@
|
|
1
|
+
function _toConsumableArray(arr) {
|
2
|
+
if (Array.isArray(arr)) {
|
3
|
+
for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) {
|
4
|
+
arr2[i] = arr[i];
|
5
|
+
}
|
6
|
+
return arr2;
|
7
|
+
} else {
|
8
|
+
return Array.from(arr);
|
9
|
+
}
|
10
|
+
}
|
11
|
+
|
12
|
+
var hasPassiveEvents = false;
|
13
|
+
|
14
|
+
if (typeof window !== "undefined") {
|
15
|
+
var passiveTestOptions = {
|
16
|
+
get passive() {
|
17
|
+
hasPassiveEvents = true;
|
18
|
+
return undefined;
|
19
|
+
}
|
20
|
+
};
|
21
|
+
window.addEventListener("testPassive", null, passiveTestOptions);
|
22
|
+
window.removeEventListener("testPassive", null, passiveTestOptions);
|
23
|
+
}
|
24
|
+
|
25
|
+
var 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);
|
26
|
+
|
27
|
+
var locks = [];
|
28
|
+
|
29
|
+
var documentListenerAdded = false;
|
30
|
+
|
31
|
+
var initialClientY = -1;
|
32
|
+
|
33
|
+
var previousBodyOverflowSetting = void 0;
|
34
|
+
|
35
|
+
var previousBodyPosition = void 0;
|
36
|
+
|
37
|
+
var previousBodyPaddingRight = void 0;
|
38
|
+
|
39
|
+
var allowTouchMove = function allowTouchMove(el) {
|
40
|
+
return locks.some((function(lock) {
|
41
|
+
if (lock.options.allowTouchMove && lock.options.allowTouchMove(el)) {
|
42
|
+
return true;
|
43
|
+
}
|
44
|
+
return false;
|
45
|
+
}));
|
46
|
+
};
|
47
|
+
|
48
|
+
var preventDefault = function preventDefault(rawEvent) {
|
49
|
+
var e = rawEvent || window.event;
|
50
|
+
if (allowTouchMove(e.target)) {
|
51
|
+
return true;
|
52
|
+
}
|
53
|
+
if (e.touches.length > 1) return true;
|
54
|
+
if (e.preventDefault) e.preventDefault();
|
55
|
+
return false;
|
56
|
+
};
|
57
|
+
|
58
|
+
var setOverflowHidden = function setOverflowHidden(options) {
|
59
|
+
if (previousBodyPaddingRight === undefined) {
|
60
|
+
var _reserveScrollBarGap = !!options && options.reserveScrollBarGap === true;
|
61
|
+
var scrollBarGap = window.innerWidth - document.documentElement.clientWidth;
|
62
|
+
if (_reserveScrollBarGap && scrollBarGap > 0) {
|
63
|
+
var computedBodyPaddingRight = parseInt(window.getComputedStyle(document.body).getPropertyValue("padding-right"), 10);
|
64
|
+
previousBodyPaddingRight = document.body.style.paddingRight;
|
65
|
+
document.body.style.paddingRight = computedBodyPaddingRight + scrollBarGap + "px";
|
66
|
+
}
|
67
|
+
}
|
68
|
+
if (previousBodyOverflowSetting === undefined) {
|
69
|
+
previousBodyOverflowSetting = document.body.style.overflow;
|
70
|
+
document.body.style.overflow = "hidden";
|
71
|
+
}
|
72
|
+
};
|
73
|
+
|
74
|
+
var restoreOverflowSetting = function restoreOverflowSetting() {
|
75
|
+
if (previousBodyPaddingRight !== undefined) {
|
76
|
+
document.body.style.paddingRight = previousBodyPaddingRight;
|
77
|
+
previousBodyPaddingRight = undefined;
|
78
|
+
}
|
79
|
+
if (previousBodyOverflowSetting !== undefined) {
|
80
|
+
document.body.style.overflow = previousBodyOverflowSetting;
|
81
|
+
previousBodyOverflowSetting = undefined;
|
82
|
+
}
|
83
|
+
};
|
84
|
+
|
85
|
+
var setPositionFixed = function setPositionFixed() {
|
86
|
+
return window.requestAnimationFrame((function() {
|
87
|
+
if (previousBodyPosition === undefined) {
|
88
|
+
previousBodyPosition = {
|
89
|
+
position: document.body.style.position,
|
90
|
+
top: document.body.style.top,
|
91
|
+
left: document.body.style.left
|
92
|
+
};
|
93
|
+
var _window = window, scrollY = _window.scrollY, scrollX = _window.scrollX, innerHeight = _window.innerHeight;
|
94
|
+
document.body.style.position = "fixed";
|
95
|
+
document.body.style.top = -scrollY;
|
96
|
+
document.body.style.left = -scrollX;
|
97
|
+
setTimeout((function() {
|
98
|
+
return window.requestAnimationFrame((function() {
|
99
|
+
var bottomBarHeight = innerHeight - window.innerHeight;
|
100
|
+
if (bottomBarHeight && scrollY >= innerHeight) {
|
101
|
+
document.body.style.top = -(scrollY + bottomBarHeight);
|
102
|
+
}
|
103
|
+
}));
|
104
|
+
}), 300);
|
105
|
+
}
|
106
|
+
}));
|
107
|
+
};
|
108
|
+
|
109
|
+
var restorePositionSetting = function restorePositionSetting() {
|
110
|
+
if (previousBodyPosition !== undefined) {
|
111
|
+
var y = -parseInt(document.body.style.top, 10);
|
112
|
+
var x = -parseInt(document.body.style.left, 10);
|
113
|
+
document.body.style.position = previousBodyPosition.position;
|
114
|
+
document.body.style.top = previousBodyPosition.top;
|
115
|
+
document.body.style.left = previousBodyPosition.left;
|
116
|
+
window.scrollTo(x, y);
|
117
|
+
previousBodyPosition = undefined;
|
118
|
+
}
|
119
|
+
};
|
120
|
+
|
121
|
+
var isTargetElementTotallyScrolled = function isTargetElementTotallyScrolled(targetElement) {
|
122
|
+
return targetElement ? targetElement.scrollHeight - targetElement.scrollTop <= targetElement.clientHeight : false;
|
123
|
+
};
|
124
|
+
|
125
|
+
var handleScroll = function handleScroll(event, targetElement) {
|
126
|
+
var clientY = event.targetTouches[0].clientY - initialClientY;
|
127
|
+
if (allowTouchMove(event.target)) {
|
128
|
+
return false;
|
129
|
+
}
|
130
|
+
if (targetElement && targetElement.scrollTop === 0 && clientY > 0) {
|
131
|
+
return preventDefault(event);
|
132
|
+
}
|
133
|
+
if (isTargetElementTotallyScrolled(targetElement) && clientY < 0) {
|
134
|
+
return preventDefault(event);
|
135
|
+
}
|
136
|
+
event.stopPropagation();
|
137
|
+
return true;
|
138
|
+
};
|
139
|
+
|
140
|
+
var disableBodyScroll$1 = function disableBodyScroll(targetElement, options) {
|
141
|
+
if (!targetElement) {
|
142
|
+
console.error("disableBodyScroll unsuccessful - targetElement must be provided when calling disableBodyScroll on IOS devices.");
|
143
|
+
return;
|
144
|
+
}
|
145
|
+
if (locks.some((function(lock) {
|
146
|
+
return lock.targetElement === targetElement;
|
147
|
+
}))) {
|
148
|
+
return;
|
149
|
+
}
|
150
|
+
var lock = {
|
151
|
+
targetElement: targetElement,
|
152
|
+
options: options || {}
|
153
|
+
};
|
154
|
+
locks = [].concat(_toConsumableArray(locks), [ lock ]);
|
155
|
+
if (isIosDevice) {
|
156
|
+
setPositionFixed();
|
157
|
+
} else {
|
158
|
+
setOverflowHidden(options);
|
159
|
+
}
|
160
|
+
if (isIosDevice) {
|
161
|
+
targetElement.ontouchstart = function(event) {
|
162
|
+
if (event.targetTouches.length === 1) {
|
163
|
+
initialClientY = event.targetTouches[0].clientY;
|
164
|
+
}
|
165
|
+
};
|
166
|
+
targetElement.ontouchmove = function(event) {
|
167
|
+
if (event.targetTouches.length === 1) {
|
168
|
+
handleScroll(event, targetElement);
|
169
|
+
}
|
170
|
+
};
|
171
|
+
if (!documentListenerAdded) {
|
172
|
+
document.addEventListener("touchmove", preventDefault, hasPassiveEvents ? {
|
173
|
+
passive: false
|
174
|
+
} : undefined);
|
175
|
+
documentListenerAdded = true;
|
176
|
+
}
|
177
|
+
}
|
178
|
+
};
|
179
|
+
|
180
|
+
var enableBodyScroll$1 = function enableBodyScroll(targetElement) {
|
181
|
+
if (!targetElement) {
|
182
|
+
console.error("enableBodyScroll unsuccessful - targetElement must be provided when calling enableBodyScroll on IOS devices.");
|
183
|
+
return;
|
184
|
+
}
|
185
|
+
locks = locks.filter((function(lock) {
|
186
|
+
return lock.targetElement !== targetElement;
|
187
|
+
}));
|
188
|
+
if (isIosDevice) {
|
189
|
+
targetElement.ontouchstart = null;
|
190
|
+
targetElement.ontouchmove = null;
|
191
|
+
if (documentListenerAdded && locks.length === 0) {
|
192
|
+
document.removeEventListener("touchmove", preventDefault, hasPassiveEvents ? {
|
193
|
+
passive: false
|
194
|
+
} : undefined);
|
195
|
+
documentListenerAdded = false;
|
196
|
+
}
|
197
|
+
}
|
198
|
+
if (isIosDevice) {
|
199
|
+
restorePositionSetting();
|
200
|
+
} else {
|
201
|
+
restoreOverflowSetting();
|
202
|
+
}
|
203
|
+
};
|
204
|
+
|
205
|
+
addEventListener("click", (event => {
|
206
|
+
window._overlasticTarget = event.target.closest("[data-turbo-frame*=overlay]");
|
207
|
+
}));
|
208
|
+
|
209
|
+
addEventListener("turbo:before-fetch-request", (event => {
|
210
|
+
if (!window._overlasticTarget) return;
|
211
|
+
const target = window._overlasticTarget;
|
212
|
+
const type = target?.dataset?.overlayType;
|
213
|
+
const args = target?.dataset?.overlayArgs;
|
214
|
+
if (type) {
|
215
|
+
event.detail.fetchOptions.headers["Overlay-Type"] = type;
|
216
|
+
}
|
217
|
+
if (args) {
|
218
|
+
event.detail.fetchOptions.headers["Overlay-Args"] = args;
|
219
|
+
}
|
220
|
+
delete window._overlasticTarget;
|
221
|
+
}));
|
222
|
+
|
223
|
+
class DialogElement extends HTMLElement {
|
224
|
+
connectedCallback() {
|
225
|
+
disableBodyScroll(this);
|
226
|
+
this.addEventListener("click", (event => this.close(event, true)));
|
227
|
+
this.querySelector(".overlastic-close").addEventListener("click", (event => this.close(event)));
|
228
|
+
}
|
229
|
+
close(event, self = false) {
|
230
|
+
if (self && event.target !== this) return;
|
231
|
+
enableBodyScroll(this);
|
232
|
+
setTimeout((() => {
|
233
|
+
this.remove();
|
234
|
+
}), 5);
|
235
|
+
}
|
236
|
+
}
|
237
|
+
|
238
|
+
customElements.define("overlastic-dialog", DialogElement);
|
239
|
+
|
240
|
+
class PaneElement extends DialogElement {
|
241
|
+
connectedCallback() {
|
242
|
+
super.connectedCallback();
|
243
|
+
const lastVisit = Turbo.navigator.history.location;
|
244
|
+
if (!window.modalVisitStack) {
|
245
|
+
window.modalVisitStack = [];
|
246
|
+
}
|
247
|
+
window.modalVisitStack.push(lastVisit);
|
248
|
+
Turbo.navigator.history.push(new URL(this.parentElement.src));
|
249
|
+
}
|
250
|
+
close(event, self = false) {
|
251
|
+
if (self && event.target !== this) return;
|
252
|
+
super.close(event, self);
|
253
|
+
if (window.modalVisitStack.length > 0) {
|
254
|
+
Turbo.navigator.history.replace(window.modalVisitStack.pop());
|
255
|
+
}
|
256
|
+
}
|
257
|
+
}
|
258
|
+
|
259
|
+
customElements.define("overlastic-pane", PaneElement);
|
260
|
+
|
261
|
+
window.disableBodyScroll = disableBodyScroll$1;
|
262
|
+
|
263
|
+
window.enableBodyScroll = enableBodyScroll$1;
|
@@ -0,0 +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=[],i=!1,r=-1,l=void 0,d=void 0,s=void 0,a=function(e){return n.some((function(t){return!(!t.options.allowTouchMove||!t.options.allowTouchMove(e))}))},c=function(e){var t=e||window.event;return!!a(t.target)||(t.touches.length>1||(t.preventDefault&&t.preventDefault(),!1))};addEventListener("click",(e=>{window._overlasticTarget=e.target.closest("[data-turbo-frame*=overlay]")})),addEventListener("turbo:before-fetch-request",(e=>{if(!window._overlasticTarget)return;const t=window._overlasticTarget,o=t?.dataset?.overlayType,n=t?.dataset?.overlayArgs;o&&(e.detail.fetchOptions.headers["Overlay-Type"]=o),n&&(e.detail.fetchOptions.headers["Overlay-Args"]=n),delete window._overlasticTarget}));class u extends HTMLElement{connectedCallback(){disableBodyScroll(this),this.addEventListener("click",(e=>this.close(e,!0))),this.querySelector(".overlastic-close").addEventListener("click",(e=>this.close(e)))}close(e,t=!1){t&&e.target!==this||(enableBodyScroll(this),setTimeout((()=>{this.remove()}),5))}}customElements.define("overlastic-dialog",u);customElements.define("overlastic-pane",class extends u{connectedCallback(){super.connectedCallback();const e=Turbo.navigator.history.location;window.modalVisitStack||(window.modalVisitStack=[]),window.modalVisitStack.push(e),Turbo.navigator.history.push(new URL(this.parentElement.src))}close(e,t=!1){t&&e.target!==this||(super.close(e,t),window.modalVisitStack.length>0&&Turbo.navigator.history.replace(window.modalVisitStack.pop()))}}),window.disableBodyScroll=function(t,u){if(t){if(!n.some((function(e){return e.targetElement===t}))){var v={targetElement:t,options:u||{}};n=[].concat(function(e){if(Array.isArray(e)){for(var t=0,o=Array(e.length);t<e.length;t++)o[t]=e[t];return o}return Array.from(e)}(n),[v]),o?window.requestAnimationFrame((function(){if(void 0===d){d={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===l&&(l=document.body.style.overflow,document.body.style.overflow="hidden")}(u),o&&(t.ontouchstart=function(e){1===e.targetTouches.length&&(r=e.targetTouches[0].clientY)},t.ontouchmove=function(e){1===e.targetTouches.length&&function(e,t){var o=e.targetTouches[0].clientY-r;!a(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!==d){var e=-parseInt(document.body.style.top,10),t=-parseInt(document.body.style.left,10);document.body.style.position=d.position,document.body.style.top=d.top,document.body.style.left=d.left,window.scrollTo(t,e),d=void 0}}():(void 0!==s&&(document.body.style.paddingRight=s,s=void 0),void 0!==l&&(document.body.style.overflow=l,l=void 0))):console.error("enableBodyScroll unsuccessful - targetElement must be provided when calling enableBodyScroll on IOS devices.")};
|
2
|
+
//# sourceMappingURL=overlastic.min.js.map
|
@@ -0,0 +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","addEventListener(\"click\", event => {\n window._overlasticTarget = event.target.closest(\"[data-turbo-frame*=overlay]\")\n})\n\naddEventListener(\"turbo:before-fetch-request\", event => {\n if (!window._overlasticTarget) return\n\n const target = window._overlasticTarget\n const type = target?.dataset?.overlayType\n const args = target?.dataset?.overlayArgs\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 delete window._overlasticTarget\n})\n","export default class DialogElement extends HTMLElement {\n connectedCallback() {\n disableBodyScroll(this)\n\n this.addEventListener(\"click\", event => this.close(event, true))\n this.querySelector(\".overlastic-close\").addEventListener(\"click\", event => this.close(event))\n }\n\n close(event, self = false) {\n if (self && event.target !== this) return\n\n enableBodyScroll(this)\n\n // Avoid removing before sending dispatching other events (like form submissions)\n setTimeout(() => {\n this.remove()\n }, 5)\n }\n}\n\ncustomElements.define(\"overlastic-dialog\", DialogElement)\n","import DialogElement from \"./dialogElement\"\n\nclass PaneElement extends DialogElement {\n connectedCallback() {\n super.connectedCallback()\n\n const lastVisit = Turbo.navigator.history.location\n\n if (!window.modalVisitStack) {\n window.modalVisitStack = []\n }\n\n window.modalVisitStack.push(lastVisit)\n Turbo.navigator.history.push(new URL(this.parentElement.src))\n }\n\n close(event, self = false) {\n if (self && event.target !== this) return\n\n super.close(event, self)\n\n if (window.modalVisitStack.length > 0) {\n Turbo.navigator.history.replace(window.modalVisitStack.pop())\n }\n }\n}\n\ncustomElements.define(\"overlastic-pane\", PaneElement)\n","import { disableBodyScroll, enableBodyScroll } from \"body-scroll-lock\"\n\nimport \"./clickInterceptor\"\nimport \"./dialogElement\"\nimport \"./paneElement\"\n\nwindow.disableBodyScroll = disableBodyScroll\nwindow.enableBodyScroll = enableBodyScroll\n"],"names":["hasPassiveEvents","window","passiveTestOptions","passive","addEventListener","removeEventListener","isIosDevice","navigator","platform","test","maxTouchPoints","locks","documentListenerAdded","initialClientY","previousBodyOverflowSetting","previousBodyPosition","previousBodyPaddingRight","allowTouchMove","el","some","lock","options","preventDefault","rawEvent","e","event","target","touches","length","_overlasticTarget","closest","type","dataset","overlayType","args","overlayArgs","detail","fetchOptions","headers","DialogElement","HTMLElement","[object Object]","disableBodyScroll","this","close","querySelector","self","enableBodyScroll","setTimeout","remove","customElements","define","super","connectedCallback","lastVisit","Turbo","history","location","modalVisitStack","push","URL","parentElement","src","replace","pop","targetElement","concat","arr","Array","isArray","i","arr2","from","_toConsumableArray","requestAnimationFrame","undefined","position","document","body","style","top","left","_window","scrollY","scrollX","innerHeight","bottomBarHeight","_reserveScrollBarGap","reserveScrollBarGap","scrollBarGap","innerWidth","documentElement","clientWidth","computedBodyPaddingRight","parseInt","getComputedStyle","getPropertyValue","paddingRight","overflow","setOverflowHidden","ontouchstart","targetTouches","clientY","ontouchmove","scrollTop","scrollHeight","clientHeight","isTargetElementTotallyScrolled","stopPropagation","handleScroll","console","error","filter","y","x","scrollTo","restorePositionSetting"],"mappings":"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"}
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Overlastic::Concerns::OverlayHandling
|
2
|
+
extend ActiveSupport::Concern
|
3
|
+
|
4
|
+
included do
|
5
|
+
before_action :add_overlay_variant
|
6
|
+
|
7
|
+
private
|
8
|
+
|
9
|
+
def add_overlay_variant
|
10
|
+
request.variant = :overlay if helpers.current_overlay_name.present?
|
11
|
+
end
|
12
|
+
|
13
|
+
def render(*args, &block)
|
14
|
+
if request.variant.overlay?
|
15
|
+
super html: helpers.render_overlay { render_to_string(*args, &block) }
|
16
|
+
else
|
17
|
+
super
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module Overlastic::NavigationHelper
|
2
|
+
def link_to_overlay(name = nil, options = nil, html_options = nil, &block)
|
3
|
+
method_type = __callee__.to_s.delete_prefix("link_to_")
|
4
|
+
method_type = nil if method_type == "overlay"
|
5
|
+
|
6
|
+
if block_given?
|
7
|
+
options ||= {}
|
8
|
+
options = options.stringify_keys
|
9
|
+
options["data"] ||= {}
|
10
|
+
|
11
|
+
type = options.delete("overlay_type") || method_type
|
12
|
+
options["data"][:overlay_type] = type if type.present?
|
13
|
+
|
14
|
+
action = options.delete("overlay_action") || Overlastic.configuration.default_action
|
15
|
+
options["data"][:turbo_frame] = turbo_frame_from_overlastic_action(action)
|
16
|
+
|
17
|
+
args = options.delete("overlay_args")
|
18
|
+
options["data"][:overlay_args] = args.to_json if args.present?
|
19
|
+
|
20
|
+
link_to(name, options, &block)
|
21
|
+
else
|
22
|
+
html_options ||= {}
|
23
|
+
html_options = html_options.stringify_keys
|
24
|
+
html_options["data"] ||= {}
|
25
|
+
|
26
|
+
type = html_options.delete("overlay_type") || method_type
|
27
|
+
html_options["data"][:overlay_type] = type if type.present?
|
28
|
+
|
29
|
+
action = html_options.delete("overlay_action") || Overlastic.configuration.default_action
|
30
|
+
html_options["data"][:turbo_frame] = turbo_frame_from_overlastic_action(action)
|
31
|
+
|
32
|
+
args = html_options.delete("overlay_args")
|
33
|
+
html_options["data"][:overlay_args] = args.to_json if args.present?
|
34
|
+
|
35
|
+
link_to(name, options, html_options, &block)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
Overlastic.configuration.overlay_types.each do |overlay_type|
|
40
|
+
alias_method :"link_to_#{overlay_type}", :link_to_overlay
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
def turbo_frame_from_overlastic_action(action)
|
46
|
+
case action
|
47
|
+
when :stack
|
48
|
+
next_overlay_name
|
49
|
+
when :replace_last
|
50
|
+
current_overlay_name
|
51
|
+
when :replace_all
|
52
|
+
:overlay1
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Overlastic::OverlaysHelper
|
2
|
+
def overlastic_tag
|
3
|
+
turbo_frame_tag :overlay1, target: :_top
|
4
|
+
end
|
5
|
+
|
6
|
+
def current_overlay_name
|
7
|
+
return unless request.headers["Turbo-Frame"].to_s.starts_with?("overlay")
|
8
|
+
|
9
|
+
request.headers["Turbo-Frame"].to_sym
|
10
|
+
end
|
11
|
+
|
12
|
+
def next_overlay_name
|
13
|
+
current_number = current_overlay_name.to_s.scan(/\d+/)&.first.to_i
|
14
|
+
|
15
|
+
"overlay#{current_number + 1}".to_sym
|
16
|
+
end
|
17
|
+
|
18
|
+
def render_overlay(locals = {}, &block)
|
19
|
+
string = capture(&block)
|
20
|
+
type = request.headers["Overlay-Type"] || Overlastic.configuration.default_overlay
|
21
|
+
args_header = request.headers["Overlay-Args"]
|
22
|
+
overlay_args = JSON.parse(request.headers["Overlay-Args"]) if args_header.present?
|
23
|
+
locals.merge! overlay_args.to_h.symbolize_keys
|
24
|
+
|
25
|
+
render(Overlastic.configuration.public_send(:"#{type}_overlay_view_path"), locals) { string }
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
addEventListener("click", event => {
|
2
|
+
window._overlasticTarget = event.target.closest("[data-turbo-frame*=overlay]")
|
3
|
+
})
|
4
|
+
|
5
|
+
addEventListener("turbo:before-fetch-request", event => {
|
6
|
+
if (!window._overlasticTarget) return
|
7
|
+
|
8
|
+
const target = window._overlasticTarget
|
9
|
+
const type = target?.dataset?.overlayType
|
10
|
+
const args = target?.dataset?.overlayArgs
|
11
|
+
|
12
|
+
if (type) {
|
13
|
+
event.detail.fetchOptions.headers["Overlay-Type"] = type
|
14
|
+
}
|
15
|
+
|
16
|
+
if (args) {
|
17
|
+
event.detail.fetchOptions.headers["Overlay-Args"] = args
|
18
|
+
}
|
19
|
+
|
20
|
+
delete window._overlasticTarget
|
21
|
+
})
|
@@ -0,0 +1,21 @@
|
|
1
|
+
export default class DialogElement extends HTMLElement {
|
2
|
+
connectedCallback() {
|
3
|
+
disableBodyScroll(this)
|
4
|
+
|
5
|
+
this.addEventListener("click", event => this.close(event, true))
|
6
|
+
this.querySelector(".overlastic-close").addEventListener("click", event => this.close(event))
|
7
|
+
}
|
8
|
+
|
9
|
+
close(event, self = false) {
|
10
|
+
if (self && event.target !== this) return
|
11
|
+
|
12
|
+
enableBodyScroll(this)
|
13
|
+
|
14
|
+
// Avoid removing before sending dispatching other events (like form submissions)
|
15
|
+
setTimeout(() => {
|
16
|
+
this.remove()
|
17
|
+
}, 5)
|
18
|
+
}
|
19
|
+
}
|
20
|
+
|
21
|
+
customElements.define("overlastic-dialog", DialogElement)
|
@@ -0,0 +1,28 @@
|
|
1
|
+
import DialogElement from "./dialogElement"
|
2
|
+
|
3
|
+
class PaneElement extends DialogElement {
|
4
|
+
connectedCallback() {
|
5
|
+
super.connectedCallback()
|
6
|
+
|
7
|
+
const lastVisit = Turbo.navigator.history.location
|
8
|
+
|
9
|
+
if (!window.modalVisitStack) {
|
10
|
+
window.modalVisitStack = []
|
11
|
+
}
|
12
|
+
|
13
|
+
window.modalVisitStack.push(lastVisit)
|
14
|
+
Turbo.navigator.history.push(new URL(this.parentElement.src))
|
15
|
+
}
|
16
|
+
|
17
|
+
close(event, self = false) {
|
18
|
+
if (self && event.target !== this) return
|
19
|
+
|
20
|
+
super.close(event, self)
|
21
|
+
|
22
|
+
if (window.modalVisitStack.length > 0) {
|
23
|
+
Turbo.navigator.history.replace(window.modalVisitStack.pop())
|
24
|
+
}
|
25
|
+
}
|
26
|
+
}
|
27
|
+
|
28
|
+
customElements.define("overlastic-pane", PaneElement)
|
@@ -0,0 +1,28 @@
|
|
1
|
+
<% title ||= "" %>
|
2
|
+
|
3
|
+
<%= turbo_frame_tag current_overlay_name do %>
|
4
|
+
<overlastic-dialog style="height:736px;background-color:rgba(107, 114, 128, 0.5);justify-content:center;align-items:center;width: 100vw;display:flex;z-index:50;left:0px;top:0px;position:fixed;box-sizing:border-box;border-width:0px;border-style:solid;border-color:rgb(229, 231, 235);">
|
5
|
+
<div style="width: 50%;justify-content:center;align-items:center;flex-direction:column;max-width:672px;height:662.398px;display:flex;box-sizing:border-box;border-width:0px;border-style:solid;border-color:rgb(229, 231, 235);">
|
6
|
+
<div style="padding-top:32px;padding-bottom:32px;box-shadow:rgba(0, 0, 0, 0) 0px 0px 0px 0px, rgba(0, 0, 0, 0) 0px 0px 0px 0px, rgba(0, 0, 0, 0.1) 0px 4px 6px -1px, rgba(0, 0, 0, 0.1) 0px 2px 4px -2px;background-color:rgb(255, 255, 255);overflow:hidden;box-sizing:border-box;border-width:0px;border-style:solid;border-color:rgb(229, 231, 235);">
|
7
|
+
<div style="padding-left:32px;padding-right:32px;justify-content:space-between;align-items:center;display:flex;box-sizing:border-box;border-width:0px;border-style:solid;border-color:rgb(229, 231, 235);">
|
8
|
+
<label style="color:rgb(55, 65, 81);font-weight:600;font-size:18px;line-height:28px;text-align:center;box-sizing:border-box;border-width:0px;border-style:solid;border-color:rgb(229, 231, 235);">
|
9
|
+
<%= title %>
|
10
|
+
</label>
|
11
|
+
|
12
|
+
<span class="overlastic-close" style="color:rgb(75, 85, 99);cursor:pointer;box-sizing:border-box;border-width:0px;border-style:solid;border-color:rgb(229, 231, 235);">
|
13
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512" style="width: 1.25rem;height:20px;display:block;vertical-align:middle;box-sizing:border-box;border-width:0px;border-style:solid;border-color:rgb(229, 231, 235);fill:currentColor;">
|
14
|
+
<!--! Font Awesome Pro 6.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2022 Fonticons, Inc. -->
|
15
|
+
<path d="M310.6 150.6c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0L160 210.7 54.6 105.4c-12.5-12.5-32.8-12.5-45.3 0s-12.5 32.8 0 45.3L114.7 256 9.4 361.4c-12.5 12.5-12.5 32.8 0 45.3s32.8 12.5 45.3 0L160 301.3 265.4 406.6c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3L205.3 256 310.6 150.6z" style="box-sizing:border-box;border-width:0px;border-style:solid;border-color:rgb(229, 231, 235);"></path>
|
16
|
+
</svg>
|
17
|
+
</span>
|
18
|
+
</div>
|
19
|
+
|
20
|
+
<div style="padding-left:32px;padding-right:32px;overscroll-behavior:contain;overflow-y: auto;max-height:calc(100% - 20px);position:relative;box-sizing:border-box;border-width:0px;border-style:solid;border-color:rgb(229, 231, 235);">
|
21
|
+
<%= yield %>
|
22
|
+
</div>
|
23
|
+
</div>
|
24
|
+
</div>
|
25
|
+
</overlastic-dialog>
|
26
|
+
|
27
|
+
<%= turbo_frame_tag next_overlay_name, target: :_top %>
|
28
|
+
<% end %>
|
@@ -0,0 +1,22 @@
|
|
1
|
+
<%= turbo_frame_tag current_overlay_name do %>
|
2
|
+
<overlastic-pane style="background-color:rgba(107, 114, 128, 0.5);justify-content:flex-end;width: 100vw;height:736px;display:flex;z-index:40;left:0px;top:0px;position:fixed;box-sizing:border-box;border-width:0px;border-style:solid;border-color:rgb(229, 231, 235);">
|
3
|
+
<div style="width: 66.6667%;align-items:flex-end;flex-direction:column;animation:0.2s ease 0s 1 normal both running modal;height:736px;display:flex;box-sizing:border-box;border-width:0px;border-style:solid;border-color:rgb(229, 231, 235);">
|
4
|
+
<div style="box-shadow:rgba(0, 0, 0, 0) 0px 0px 0px 0px, rgba(0, 0, 0, 0) 0px 0px 0px 0px, rgba(0, 0, 0, 0.1) 0px 4px 6px -1px, rgba(0, 0, 0, 0.1) 0px 2px 4px -2px;padding-top:20px;padding-bottom:20px;background-color:rgb(249, 250, 251);border-top-left-radius:8px;border-bottom-left-radius:8px;overflow:hidden;width: 100%;height:736px;box-sizing:border-box;border-width:0px;border-style:solid;border-color:rgb(229, 231, 235);">
|
5
|
+
<div style="padding-left:20px;padding-right:20px;justify-content:space-between;align-items:center;display:flex;margin-bottom:12px;box-sizing:border-box;border-width:0px;border-style:solid;border-color:rgb(229, 231, 235);">
|
6
|
+
<span class="overlastic-close" style="color:rgb(75, 85, 99);cursor:pointer;box-sizing:border-box;border-width:0px;border-style:solid;border-color:rgb(229, 231, 235);">
|
7
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512" style="width: 2rem;height:32px;display:block;vertical-align:middle;box-sizing:border-box;border-width:0px;border-style:solid;border-color:rgb(229, 231, 235);fill:currentColor;">
|
8
|
+
<!--! Font Awesome Pro 6.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2022 Fonticons, Inc. -->
|
9
|
+
<path d="M310.6 150.6c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0L160 210.7 54.6 105.4c-12.5-12.5-32.8-12.5-45.3 0s-12.5 32.8 0 45.3L114.7 256 9.4 361.4c-12.5 12.5-12.5 32.8 0 45.3s32.8 12.5 45.3 0L160 301.3 265.4 406.6c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3L205.3 256 310.6 150.6z" style="box-sizing:border-box;border-width:0px;border-style:solid;border-color:rgb(229, 231, 235);"></path>
|
10
|
+
</svg>
|
11
|
+
</span>
|
12
|
+
</div>
|
13
|
+
|
14
|
+
<div style="padding-left:32px;padding-right:32px;overscroll-behavior:contain;overflow-y: auto;max-height:calc(100% - 56px);position:relative;box-sizing:border-box;border-width:0px;border-style:solid;border-color:rgb(229, 231, 235);">
|
15
|
+
<%= yield %>
|
16
|
+
</div>
|
17
|
+
</div>
|
18
|
+
</div>
|
19
|
+
</overlastic-pane>
|
20
|
+
|
21
|
+
<%= turbo_frame_tag next_overlay_name, target: :_top %>
|
22
|
+
<% end %>
|
@@ -0,0 +1,28 @@
|
|
1
|
+
<% title ||= "" %>
|
2
|
+
|
3
|
+
<%= turbo_frame_tag current_overlay_name do %>
|
4
|
+
<overlastic-dialog class="fixed top-0 left-0 z-50 flex justify-center w-screen h-screen-safe items-center bg-gray-500 bg-opacity-50">
|
5
|
+
<div class="w-11/12 sm:w-5/6 lg:w-1/2 max-w-2xl h-[90vh] flex flex-col justify-center items-center">
|
6
|
+
<div class="py-4 sm:py-8 bg-white shadow-md overflow-hidden">
|
7
|
+
<div class="px-4 sm:px-8 flex justify-between items-center">
|
8
|
+
<label class="text-lg text-gray-700 text-center font-semibold">
|
9
|
+
<%= title %>
|
10
|
+
</label>
|
11
|
+
|
12
|
+
<span class="overlastic-close cursor-pointer text-gray-600">
|
13
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512" class="w-5 h-5 fill-current">
|
14
|
+
<!--! Font Awesome Pro 6.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2022 Fonticons, Inc. -->
|
15
|
+
<path d="M310.6 150.6c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0L160 210.7 54.6 105.4c-12.5-12.5-32.8-12.5-45.3 0s-12.5 32.8 0 45.3L114.7 256 9.4 361.4c-12.5 12.5-12.5 32.8 0 45.3s32.8 12.5 45.3 0L160 301.3 265.4 406.6c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3L205.3 256 310.6 150.6z"/>
|
16
|
+
</svg>
|
17
|
+
</span>
|
18
|
+
</div>
|
19
|
+
|
20
|
+
<div class="px-4 sm:px-8 relative overflow-y-auto overscroll-contain max-h-[calc(100%-1.25rem)]">
|
21
|
+
<%= yield %>
|
22
|
+
</div>
|
23
|
+
</div>
|
24
|
+
</div>
|
25
|
+
</overlastic-dialog>
|
26
|
+
|
27
|
+
<%= turbo_frame_tag next_overlay_name, target: :_top %>
|
28
|
+
<% end %>
|
@@ -0,0 +1,22 @@
|
|
1
|
+
<%= turbo_frame_tag current_overlay_name do %>
|
2
|
+
<overlastic-pane class="fixed top-0 left-0 z-40 flex justify-end w-screen h-screen bg-gray-500 bg-opacity-50">
|
3
|
+
<div class="w-full sm:w-5/6 lg:w-8/12 h-full flex flex-col items-end animate-modal">
|
4
|
+
<div id="split-container" class="py-5 bg-gray-50 rounded-l-lg shadow-md overflow-hidden w-full h-full">
|
5
|
+
<div class="px-5 mb-3 flex justify-between items-center">
|
6
|
+
<span class="overlastic-close cursor-pointer text-gray-600">
|
7
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512" class="w-8 h-8 fill-current">
|
8
|
+
<!--! Font Awesome Pro 6.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2022 Fonticons, Inc. -->
|
9
|
+
<path d="M310.6 150.6c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0L160 210.7 54.6 105.4c-12.5-12.5-32.8-12.5-45.3 0s-12.5 32.8 0 45.3L114.7 256 9.4 361.4c-12.5 12.5-12.5 32.8 0 45.3s32.8 12.5 45.3 0L160 301.3 265.4 406.6c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3L205.3 256 310.6 150.6z"/>
|
10
|
+
</svg>
|
11
|
+
</span>
|
12
|
+
</div>
|
13
|
+
|
14
|
+
<div class="px-8 relative overflow-y-auto overscroll-contain max-h-[calc(100%-3.5rem)]">
|
15
|
+
<%= yield %>
|
16
|
+
</div>
|
17
|
+
</div>
|
18
|
+
</div>
|
19
|
+
</overlastic-pane>
|
20
|
+
|
21
|
+
<%= turbo_frame_tag next_overlay_name, target: :_top %>
|
22
|
+
<% end %>
|
@@ -0,0 +1,8 @@
|
|
1
|
+
say "Import Overlastic"
|
2
|
+
append_to_file "app/javascript/application.js", %(import "overlastic"\n)
|
3
|
+
|
4
|
+
say "Pin Overlastic"
|
5
|
+
append_to_file "config/importmap.rb", %(pin "overlastic", to: "overlastic.min.js", preload: true\n)
|
6
|
+
|
7
|
+
say "Add Overlastic tag in application layout"
|
8
|
+
insert_into_file Rails.root.join("app/views/layouts/application.html.erb"), "\n\n <%= overlastic_tag %>", before: /\s*<\/body>/
|
@@ -0,0 +1,5 @@
|
|
1
|
+
say "Add Overlastic JS include tag in application layout"
|
2
|
+
insert_into_file Rails.root.join("app/views/layouts/application.html.erb"), "\n <%= javascript_include_tag \"overlastic.min\", \"data-turbo-track\": \"reload\", defer: true %>", before: /\s*<\/head>/
|
3
|
+
|
4
|
+
say "Add Overlastic tag in application layout"
|
5
|
+
insert_into_file Rails.root.join("app/views/layouts/application.html.erb"), "\n\n <%= overlastic_tag %>", before: /\s*<\/body>/
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Overlastic
|
2
|
+
class Configuration
|
3
|
+
attr_accessor :overlay_types, :default_overlay, :default_action
|
4
|
+
|
5
|
+
def initialize
|
6
|
+
self.overlay_types = %i[dialog pane]
|
7
|
+
self.default_overlay = :dialog
|
8
|
+
self.default_action = :stack
|
9
|
+
end
|
10
|
+
|
11
|
+
def overlay_types=(types)
|
12
|
+
overlay_types&.each do |overlay_type|
|
13
|
+
undef :"#{overlay_type}_overlay_view_path"
|
14
|
+
undef :"#{overlay_type}_overlay_view_path="
|
15
|
+
end
|
16
|
+
|
17
|
+
@overlay_types = types
|
18
|
+
|
19
|
+
overlay_types.each do |overlay_type|
|
20
|
+
self.class.attr_accessor :"#{overlay_type}_overlay_view_path"
|
21
|
+
|
22
|
+
public_send :"#{overlay_type}_overlay_view_path=", "shared/overlays/#{overlay_type}"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require "rails/engine"
|
2
|
+
|
3
|
+
module Overlastic
|
4
|
+
class Engine < Rails::Engine
|
5
|
+
isolate_namespace Overlastic
|
6
|
+
|
7
|
+
config.eager_load_namespaces << Overlastic
|
8
|
+
config.autoload_once_paths = %W(
|
9
|
+
#{root}/app/controllers
|
10
|
+
#{root}/app/controllers/concerns
|
11
|
+
#{root}/app/helpers
|
12
|
+
)
|
13
|
+
|
14
|
+
initializer "overlastic.assets" do
|
15
|
+
if Rails.application.config.respond_to?(:assets)
|
16
|
+
Rails.application.config.assets.precompile += %w[overlastic.min.js]
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
initializer "overlastic.helpers", before: :load_config_initializers do
|
21
|
+
ActiveSupport.on_load(:action_controller_base) do
|
22
|
+
include Overlastic::Concerns::OverlayHandling
|
23
|
+
|
24
|
+
helper Overlastic::Engine.helpers
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
data/lib/overlastic.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
require "overlastic/engine"
|
2
|
+
require "overlastic/configuration"
|
3
|
+
|
4
|
+
module Overlastic
|
5
|
+
extend ActiveSupport::Autoload
|
6
|
+
|
7
|
+
class << self
|
8
|
+
def configuration
|
9
|
+
@configuration ||= Overlastic::Configuration.new
|
10
|
+
end
|
11
|
+
|
12
|
+
def configure
|
13
|
+
yield(configuration)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
def run_overlastic_install_template(path)
|
2
|
+
system "#{RbConfig.ruby} ./bin/rails app:template LOCATION=#{File.expand_path("../install/#{path}.rb", __dir__)}"
|
3
|
+
end
|
4
|
+
|
5
|
+
namespace :overlastic do
|
6
|
+
desc "Install Overlastic into the app"
|
7
|
+
task :install do
|
8
|
+
if Rails.root.join("config/importmap.rb").exist?
|
9
|
+
Rake::Task["overlastic:install:importmap"].invoke
|
10
|
+
else
|
11
|
+
Rake::Task["overlastic:install:node"].invoke
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
namespace :install do
|
16
|
+
desc "Install Overlastic into the app with asset pipeline"
|
17
|
+
task :importmap do
|
18
|
+
run_overlastic_install_template "overlastic_with_importmap"
|
19
|
+
end
|
20
|
+
|
21
|
+
desc "Install Overlastic into the app with node"
|
22
|
+
task :node do
|
23
|
+
run_overlastic_install_template "overlastic_with_node"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
metadata
ADDED
@@ -0,0 +1,108 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: overlastic
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Martin Zamuner
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2022-09-12 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: activejob
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 6.0.0
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 6.0.0
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: actionpack
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 6.0.0
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 6.0.0
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: railties
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 6.0.0
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 6.0.0
|
55
|
+
description:
|
56
|
+
email: martinzamuner@gmail.com
|
57
|
+
executables: []
|
58
|
+
extensions: []
|
59
|
+
extra_rdoc_files: []
|
60
|
+
files:
|
61
|
+
- MIT-LICENSE
|
62
|
+
- README.md
|
63
|
+
- Rakefile
|
64
|
+
- app/assets/javascripts/overlastic.js
|
65
|
+
- app/assets/javascripts/overlastic.min.js
|
66
|
+
- app/assets/javascripts/overlastic.min.js.map
|
67
|
+
- app/controllers/overlastic/concerns/overlay_handling.rb
|
68
|
+
- app/helpers/overlastic/navigation_helper.rb
|
69
|
+
- app/helpers/overlastic/overlays_helper.rb
|
70
|
+
- app/javascript/overlastic/clickInterceptor.js
|
71
|
+
- app/javascript/overlastic/dialogElement.js
|
72
|
+
- app/javascript/overlastic/index.js
|
73
|
+
- app/javascript/overlastic/paneElement.js
|
74
|
+
- app/views/shared/overlays/_dialog.html.erb
|
75
|
+
- app/views/shared/overlays/_pane.html.erb
|
76
|
+
- app/views/shared/overlays/tailwind/_dialog.html.erb
|
77
|
+
- app/views/shared/overlays/tailwind/_pane.html.erb
|
78
|
+
- lib/install/overlastic_with_importmap.rb
|
79
|
+
- lib/install/overlastic_with_node.rb
|
80
|
+
- lib/overlastic.rb
|
81
|
+
- lib/overlastic/configuration.rb
|
82
|
+
- lib/overlastic/engine.rb
|
83
|
+
- lib/overlastic/version.rb
|
84
|
+
- lib/tasks/overlastic_tasks.rake
|
85
|
+
homepage: https://github.com/martinzamuner/overlastic
|
86
|
+
licenses:
|
87
|
+
- MIT
|
88
|
+
metadata: {}
|
89
|
+
post_install_message:
|
90
|
+
rdoc_options: []
|
91
|
+
require_paths:
|
92
|
+
- lib
|
93
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
94
|
+
requirements:
|
95
|
+
- - ">="
|
96
|
+
- !ruby/object:Gem::Version
|
97
|
+
version: 2.6.0
|
98
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
99
|
+
requirements:
|
100
|
+
- - ">="
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: '0'
|
103
|
+
requirements: []
|
104
|
+
rubygems_version: 3.2.22
|
105
|
+
signing_key:
|
106
|
+
specification_version: 4
|
107
|
+
summary: Fantastically easy overlays using Hotwire.
|
108
|
+
test_files: []
|