overlastic 0.1.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 +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: []
|