katalyst-kpop 3.0.0.beta.1 → 3.0.0.beta.2
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 +4 -4
- data/app/assets/builds/katalyst/kpop.esm.js +116 -125
- data/app/assets/builds/katalyst/kpop.js +116 -125
- data/app/assets/builds/katalyst/kpop.min.js +1 -1
- data/app/assets/builds/katalyst/kpop.min.js.map +1 -1
- data/app/components/kpop/frame_component.rb +1 -0
- data/app/javascript/kpop/application.js +2 -4
- data/app/javascript/kpop/controllers/frame_controller.js +28 -39
- data/app/javascript/kpop/turbo_actions.js +33 -0
- data/lib/katalyst/kpop/matchers/redirect_matcher.rb +1 -1
- data/lib/katalyst/kpop/matchers.rb +4 -4
- data/lib/katalyst/kpop/turbo.rb +13 -19
- data/lib/katalyst/kpop/version.rb +1 -1
- metadata +4 -6
- data/app/javascript/kpop/controllers/close_controller.js +0 -9
- data/app/javascript/kpop/controllers/redirect_controller.js +0 -22
- data/lib/katalyst/kpop/matchers/redirect_finder.rb +0 -16
- /data/app/javascript/kpop/{modals → utils}/stream_renderer.js +0 -0
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: bdd0521dfd00d4dc6d5c4f6b705d45fdcf0fa06b3a47cd6ec1b271b08b77e64a
|
|
4
|
+
data.tar.gz: 6a5480d57130797edd0e59e0e44710cd931033fcdbf01d286009e2be5bf8a5d6
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 4a8968e2712ea484dab2c01595e34474db62b94db09336fcae92450c9915c534c62980aa3d8ccee5a92bdd4c5836638c71242e668a71ed57de9715e7e6b78d4e
|
|
7
|
+
data.tar.gz: a7bd8a924421cf8f4fb509cea1893e4187e10fc6476579f598686cb9b4b259a8a16097d5b31b03f4fc805dd2362445f65a1438a74cd2c4c17162197b389848af
|
|
@@ -1,14 +1,6 @@
|
|
|
1
1
|
import { Controller } from '@hotwired/stimulus';
|
|
2
2
|
import { Turbo } from '@hotwired/turbo-rails';
|
|
3
3
|
|
|
4
|
-
class Kpop__CloseController extends Controller {
|
|
5
|
-
static outlets = ["kpop--frame"];
|
|
6
|
-
|
|
7
|
-
kpopFrameOutletConnected(frame) {
|
|
8
|
-
frame.dismiss();
|
|
9
|
-
}
|
|
10
|
-
}
|
|
11
|
-
|
|
12
4
|
class Modal {
|
|
13
5
|
constructor(id) {
|
|
14
6
|
this.id = id;
|
|
@@ -155,79 +147,6 @@ class FrameModal extends Modal {
|
|
|
155
147
|
}
|
|
156
148
|
}
|
|
157
149
|
|
|
158
|
-
class StreamModal extends Modal {
|
|
159
|
-
constructor(id, action) {
|
|
160
|
-
super(id);
|
|
161
|
-
|
|
162
|
-
this.action = action;
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
async open() {
|
|
166
|
-
await super.open();
|
|
167
|
-
|
|
168
|
-
window.history.pushState({ kpop: true, id: this.id }, "", window.location);
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
async dismiss() {
|
|
172
|
-
await super.dismiss();
|
|
173
|
-
|
|
174
|
-
if (this.isCurrentLocation) {
|
|
175
|
-
await this.pop("popstate", () => window.history.back());
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
this.frameElement.innerHTML = "";
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
beforeVisit(frame, e) {
|
|
182
|
-
super.beforeVisit(frame, e);
|
|
183
|
-
|
|
184
|
-
e.preventDefault();
|
|
185
|
-
|
|
186
|
-
frame.dismiss({ animate: false }).then(() => {
|
|
187
|
-
Turbo.visit(e.detail.url);
|
|
188
|
-
|
|
189
|
-
this.debug("before-visit-end");
|
|
190
|
-
});
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
popstate(frame, e) {
|
|
194
|
-
super.popstate(frame, e);
|
|
195
|
-
|
|
196
|
-
frame.dismiss({ animate: true, reason: "popstate" });
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
get isCurrentLocation() {
|
|
200
|
-
return window.history.state?.kpop && window.history.state?.id === this.id;
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
class StreamRenderer {
|
|
205
|
-
constructor(frame, action) {
|
|
206
|
-
this.frame = frame;
|
|
207
|
-
this.action = action;
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
render() {
|
|
211
|
-
this.frame.src = "";
|
|
212
|
-
this.frame.innerHTML = "";
|
|
213
|
-
this.frame.append(this.action.templateContent);
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
Turbo.StreamActions.kpop_open = function () {
|
|
218
|
-
const frame = () => {
|
|
219
|
-
return this.targetElements[0];
|
|
220
|
-
};
|
|
221
|
-
const animate = !frame?.kpop?.openValue;
|
|
222
|
-
|
|
223
|
-
frame()
|
|
224
|
-
.kpop.dismiss({ animate, reason: "before-turbo-stream" })
|
|
225
|
-
.then(() => {
|
|
226
|
-
new StreamRenderer(frame(), this).render();
|
|
227
|
-
frame().kpop.open(new StreamModal(this.target, this), { animate });
|
|
228
|
-
});
|
|
229
|
-
};
|
|
230
|
-
|
|
231
150
|
class Kpop__FrameController extends Controller {
|
|
232
151
|
static outlets = ["scrim"];
|
|
233
152
|
static targets = ["modal"];
|
|
@@ -284,11 +203,9 @@ class Kpop__FrameController extends Controller {
|
|
|
284
203
|
return false;
|
|
285
204
|
}
|
|
286
205
|
|
|
287
|
-
this.opening ||= this.#
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
return this.opening;
|
|
206
|
+
return (this.opening ||= this.#nextFrame(() =>
|
|
207
|
+
this.#open(modal, { animate })
|
|
208
|
+
));
|
|
292
209
|
}
|
|
293
210
|
|
|
294
211
|
async dismiss({ animate = true, reason = "" } = {}) {
|
|
@@ -297,15 +214,9 @@ class Kpop__FrameController extends Controller {
|
|
|
297
214
|
return false;
|
|
298
215
|
}
|
|
299
216
|
|
|
300
|
-
this.dismissing ||= this.#
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
return this.#nextAnimationFrame(resolve);
|
|
304
|
-
});
|
|
305
|
-
});
|
|
306
|
-
});
|
|
307
|
-
|
|
308
|
-
return this.dismissing;
|
|
217
|
+
return (this.dismissing ||= this.#nextFrame(() =>
|
|
218
|
+
this.#dismiss({ animate, reason })
|
|
219
|
+
));
|
|
309
220
|
}
|
|
310
221
|
|
|
311
222
|
// EVENTS
|
|
@@ -320,10 +231,27 @@ class Kpop__FrameController extends Controller {
|
|
|
320
231
|
event.preventDefault();
|
|
321
232
|
|
|
322
233
|
this.dismiss({ animate: true, reason: "before-frame-render" }).then(() => {
|
|
234
|
+
this.debug("resume-frame-render", event.detail.newFrame.baseURI);
|
|
323
235
|
event.detail.resume();
|
|
324
236
|
});
|
|
325
237
|
}
|
|
326
238
|
|
|
239
|
+
beforeStreamRender(event) {
|
|
240
|
+
this.debug("before-stream-render", event.detail);
|
|
241
|
+
|
|
242
|
+
const resume = event.detail.render;
|
|
243
|
+
|
|
244
|
+
// Defer rendering until dismiss is complete.
|
|
245
|
+
// Dismiss may change history so we need to wait for it to complete to avoid
|
|
246
|
+
// losing DOM changes on restoration visits.
|
|
247
|
+
event.detail.render = (stream) => {
|
|
248
|
+
(this.dismissing || Promise.resolve()).then(() => {
|
|
249
|
+
this.debug("stream-render", stream);
|
|
250
|
+
resume(stream);
|
|
251
|
+
});
|
|
252
|
+
};
|
|
253
|
+
}
|
|
254
|
+
|
|
327
255
|
beforeVisit(e) {
|
|
328
256
|
this.debug("before-visit", e.detail.url);
|
|
329
257
|
|
|
@@ -356,8 +284,8 @@ class Kpop__FrameController extends Controller {
|
|
|
356
284
|
this.modal = modal;
|
|
357
285
|
this.openValue = true;
|
|
358
286
|
|
|
359
|
-
modal.open({ animate });
|
|
360
|
-
scrim?.show({ animate });
|
|
287
|
+
await modal.open({ animate });
|
|
288
|
+
await scrim?.show({ animate });
|
|
361
289
|
|
|
362
290
|
delete this.opening;
|
|
363
291
|
|
|
@@ -381,12 +309,9 @@ class Kpop__FrameController extends Controller {
|
|
|
381
309
|
this.debug("dismiss-end");
|
|
382
310
|
}
|
|
383
311
|
|
|
384
|
-
#
|
|
385
|
-
return
|
|
386
|
-
|
|
387
|
-
resolve(callback());
|
|
388
|
-
});
|
|
389
|
-
});
|
|
312
|
+
async #nextFrame(callback) {
|
|
313
|
+
// return Promise.resolve().then(callback);
|
|
314
|
+
return new Promise(window.requestAnimationFrame).then(callback);
|
|
390
315
|
}
|
|
391
316
|
|
|
392
317
|
debug(event, ...args) {
|
|
@@ -419,26 +344,6 @@ class Kpop__ModalController extends Controller {
|
|
|
419
344
|
}
|
|
420
345
|
}
|
|
421
346
|
|
|
422
|
-
class Kpop__RedirectController extends Controller {
|
|
423
|
-
static outlets = ["kpop--frame"];
|
|
424
|
-
static values = {
|
|
425
|
-
path: String,
|
|
426
|
-
target: String,
|
|
427
|
-
};
|
|
428
|
-
|
|
429
|
-
kpopFrameOutletConnected(frame) {
|
|
430
|
-
if (this.targetValue === frame.element.id) {
|
|
431
|
-
frame.dismiss().then(() => {
|
|
432
|
-
document.getElementById(this.targetValue).src = this.pathValue;
|
|
433
|
-
});
|
|
434
|
-
} else {
|
|
435
|
-
Turbo.visit(this.pathValue, { action: "replace" });
|
|
436
|
-
}
|
|
437
|
-
|
|
438
|
-
this.element.remove();
|
|
439
|
-
}
|
|
440
|
-
}
|
|
441
|
-
|
|
442
347
|
/**
|
|
443
348
|
* Scrim controller wraps an element that creates a whole page layer.
|
|
444
349
|
* It is intended to be used behind a modal or nav drawer.
|
|
@@ -588,11 +493,97 @@ function resetStyle(element, property, previousValue) {
|
|
|
588
493
|
}
|
|
589
494
|
}
|
|
590
495
|
|
|
496
|
+
class StreamModal extends Modal {
|
|
497
|
+
constructor(id, action) {
|
|
498
|
+
super(id);
|
|
499
|
+
|
|
500
|
+
this.action = action;
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
async open() {
|
|
504
|
+
await super.open();
|
|
505
|
+
|
|
506
|
+
window.history.pushState({ kpop: true, id: this.id }, "", window.location);
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
async dismiss() {
|
|
510
|
+
await super.dismiss();
|
|
511
|
+
|
|
512
|
+
if (this.isCurrentLocation) {
|
|
513
|
+
await this.pop("popstate", () => window.history.back());
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
this.frameElement.innerHTML = "";
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
beforeVisit(frame, e) {
|
|
520
|
+
super.beforeVisit(frame, e);
|
|
521
|
+
|
|
522
|
+
e.preventDefault();
|
|
523
|
+
|
|
524
|
+
frame.dismiss({ animate: false }).then(() => {
|
|
525
|
+
Turbo.visit(e.detail.url);
|
|
526
|
+
|
|
527
|
+
this.debug("before-visit-end");
|
|
528
|
+
});
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
popstate(frame, e) {
|
|
532
|
+
super.popstate(frame, e);
|
|
533
|
+
|
|
534
|
+
frame.dismiss({ animate: true, reason: "popstate" });
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
get isCurrentLocation() {
|
|
538
|
+
return window.history.state?.kpop && window.history.state?.id === this.id;
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
class StreamRenderer {
|
|
543
|
+
constructor(frame, action) {
|
|
544
|
+
this.frame = frame;
|
|
545
|
+
this.action = action;
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
render() {
|
|
549
|
+
this.frame.src = "";
|
|
550
|
+
this.frame.innerHTML = "";
|
|
551
|
+
this.frame.append(this.action.templateContent);
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
function kpop(action) {
|
|
556
|
+
return action.targetElements[0]?.kpop;
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
Turbo.StreamActions.kpop_open = function () {
|
|
560
|
+
const animate = !kpop(this).openValue;
|
|
561
|
+
|
|
562
|
+
kpop(this)
|
|
563
|
+
?.dismiss({ animate, reason: "before-turbo-stream" })
|
|
564
|
+
.then(() => {
|
|
565
|
+
new StreamRenderer(this.targetElements[0], this).render();
|
|
566
|
+
kpop(this)?.open(new StreamModal(this.target, this), { animate });
|
|
567
|
+
});
|
|
568
|
+
};
|
|
569
|
+
|
|
570
|
+
Turbo.StreamActions.kpop_dismiss = function () {
|
|
571
|
+
kpop(this)?.dismiss({ reason: "turbo_stream.kpop.dismiss" });
|
|
572
|
+
};
|
|
573
|
+
|
|
574
|
+
Turbo.StreamActions.kpop_redirect_to = function () {
|
|
575
|
+
if (this.dataset.turboFrame === this.target) {
|
|
576
|
+
this.targetElements[0].src = this.getAttribute("href");
|
|
577
|
+
} else {
|
|
578
|
+
Turbo.visit(this.getAttribute("href"), {
|
|
579
|
+
action: this.dataset.turboAction,
|
|
580
|
+
});
|
|
581
|
+
}
|
|
582
|
+
};
|
|
583
|
+
|
|
591
584
|
const Definitions = [
|
|
592
|
-
{ identifier: "kpop--close", controllerConstructor: Kpop__CloseController },
|
|
593
585
|
{ identifier: "kpop--frame", controllerConstructor: Kpop__FrameController },
|
|
594
586
|
{ identifier: "kpop--modal", controllerConstructor: Kpop__ModalController },
|
|
595
|
-
{ identifier: "kpop--redirect", controllerConstructor: Kpop__RedirectController },
|
|
596
587
|
{ identifier: "scrim", controllerConstructor: ScrimController },
|
|
597
588
|
];
|
|
598
589
|
|
|
@@ -1,14 +1,6 @@
|
|
|
1
1
|
import { Controller } from '@hotwired/stimulus';
|
|
2
2
|
import { Turbo } from '@hotwired/turbo-rails';
|
|
3
3
|
|
|
4
|
-
class Kpop__CloseController extends Controller {
|
|
5
|
-
static outlets = ["kpop--frame"];
|
|
6
|
-
|
|
7
|
-
kpopFrameOutletConnected(frame) {
|
|
8
|
-
frame.dismiss();
|
|
9
|
-
}
|
|
10
|
-
}
|
|
11
|
-
|
|
12
4
|
class Modal {
|
|
13
5
|
constructor(id) {
|
|
14
6
|
this.id = id;
|
|
@@ -155,79 +147,6 @@ class FrameModal extends Modal {
|
|
|
155
147
|
}
|
|
156
148
|
}
|
|
157
149
|
|
|
158
|
-
class StreamModal extends Modal {
|
|
159
|
-
constructor(id, action) {
|
|
160
|
-
super(id);
|
|
161
|
-
|
|
162
|
-
this.action = action;
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
async open() {
|
|
166
|
-
await super.open();
|
|
167
|
-
|
|
168
|
-
window.history.pushState({ kpop: true, id: this.id }, "", window.location);
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
async dismiss() {
|
|
172
|
-
await super.dismiss();
|
|
173
|
-
|
|
174
|
-
if (this.isCurrentLocation) {
|
|
175
|
-
await this.pop("popstate", () => window.history.back());
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
this.frameElement.innerHTML = "";
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
beforeVisit(frame, e) {
|
|
182
|
-
super.beforeVisit(frame, e);
|
|
183
|
-
|
|
184
|
-
e.preventDefault();
|
|
185
|
-
|
|
186
|
-
frame.dismiss({ animate: false }).then(() => {
|
|
187
|
-
Turbo.visit(e.detail.url);
|
|
188
|
-
|
|
189
|
-
this.debug("before-visit-end");
|
|
190
|
-
});
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
popstate(frame, e) {
|
|
194
|
-
super.popstate(frame, e);
|
|
195
|
-
|
|
196
|
-
frame.dismiss({ animate: true, reason: "popstate" });
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
get isCurrentLocation() {
|
|
200
|
-
return window.history.state?.kpop && window.history.state?.id === this.id;
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
class StreamRenderer {
|
|
205
|
-
constructor(frame, action) {
|
|
206
|
-
this.frame = frame;
|
|
207
|
-
this.action = action;
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
render() {
|
|
211
|
-
this.frame.src = "";
|
|
212
|
-
this.frame.innerHTML = "";
|
|
213
|
-
this.frame.append(this.action.templateContent);
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
Turbo.StreamActions.kpop_open = function () {
|
|
218
|
-
const frame = () => {
|
|
219
|
-
return this.targetElements[0];
|
|
220
|
-
};
|
|
221
|
-
const animate = !frame?.kpop?.openValue;
|
|
222
|
-
|
|
223
|
-
frame()
|
|
224
|
-
.kpop.dismiss({ animate, reason: "before-turbo-stream" })
|
|
225
|
-
.then(() => {
|
|
226
|
-
new StreamRenderer(frame(), this).render();
|
|
227
|
-
frame().kpop.open(new StreamModal(this.target, this), { animate });
|
|
228
|
-
});
|
|
229
|
-
};
|
|
230
|
-
|
|
231
150
|
class Kpop__FrameController extends Controller {
|
|
232
151
|
static outlets = ["scrim"];
|
|
233
152
|
static targets = ["modal"];
|
|
@@ -284,11 +203,9 @@ class Kpop__FrameController extends Controller {
|
|
|
284
203
|
return false;
|
|
285
204
|
}
|
|
286
205
|
|
|
287
|
-
this.opening ||= this.#
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
return this.opening;
|
|
206
|
+
return (this.opening ||= this.#nextFrame(() =>
|
|
207
|
+
this.#open(modal, { animate })
|
|
208
|
+
));
|
|
292
209
|
}
|
|
293
210
|
|
|
294
211
|
async dismiss({ animate = true, reason = "" } = {}) {
|
|
@@ -297,15 +214,9 @@ class Kpop__FrameController extends Controller {
|
|
|
297
214
|
return false;
|
|
298
215
|
}
|
|
299
216
|
|
|
300
|
-
this.dismissing ||= this.#
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
return this.#nextAnimationFrame(resolve);
|
|
304
|
-
});
|
|
305
|
-
});
|
|
306
|
-
});
|
|
307
|
-
|
|
308
|
-
return this.dismissing;
|
|
217
|
+
return (this.dismissing ||= this.#nextFrame(() =>
|
|
218
|
+
this.#dismiss({ animate, reason })
|
|
219
|
+
));
|
|
309
220
|
}
|
|
310
221
|
|
|
311
222
|
// EVENTS
|
|
@@ -320,10 +231,27 @@ class Kpop__FrameController extends Controller {
|
|
|
320
231
|
event.preventDefault();
|
|
321
232
|
|
|
322
233
|
this.dismiss({ animate: true, reason: "before-frame-render" }).then(() => {
|
|
234
|
+
this.debug("resume-frame-render", event.detail.newFrame.baseURI);
|
|
323
235
|
event.detail.resume();
|
|
324
236
|
});
|
|
325
237
|
}
|
|
326
238
|
|
|
239
|
+
beforeStreamRender(event) {
|
|
240
|
+
this.debug("before-stream-render", event.detail);
|
|
241
|
+
|
|
242
|
+
const resume = event.detail.render;
|
|
243
|
+
|
|
244
|
+
// Defer rendering until dismiss is complete.
|
|
245
|
+
// Dismiss may change history so we need to wait for it to complete to avoid
|
|
246
|
+
// losing DOM changes on restoration visits.
|
|
247
|
+
event.detail.render = (stream) => {
|
|
248
|
+
(this.dismissing || Promise.resolve()).then(() => {
|
|
249
|
+
this.debug("stream-render", stream);
|
|
250
|
+
resume(stream);
|
|
251
|
+
});
|
|
252
|
+
};
|
|
253
|
+
}
|
|
254
|
+
|
|
327
255
|
beforeVisit(e) {
|
|
328
256
|
this.debug("before-visit", e.detail.url);
|
|
329
257
|
|
|
@@ -356,8 +284,8 @@ class Kpop__FrameController extends Controller {
|
|
|
356
284
|
this.modal = modal;
|
|
357
285
|
this.openValue = true;
|
|
358
286
|
|
|
359
|
-
modal.open({ animate });
|
|
360
|
-
scrim?.show({ animate });
|
|
287
|
+
await modal.open({ animate });
|
|
288
|
+
await scrim?.show({ animate });
|
|
361
289
|
|
|
362
290
|
delete this.opening;
|
|
363
291
|
|
|
@@ -381,12 +309,9 @@ class Kpop__FrameController extends Controller {
|
|
|
381
309
|
this.debug("dismiss-end");
|
|
382
310
|
}
|
|
383
311
|
|
|
384
|
-
#
|
|
385
|
-
return
|
|
386
|
-
|
|
387
|
-
resolve(callback());
|
|
388
|
-
});
|
|
389
|
-
});
|
|
312
|
+
async #nextFrame(callback) {
|
|
313
|
+
// return Promise.resolve().then(callback);
|
|
314
|
+
return new Promise(window.requestAnimationFrame).then(callback);
|
|
390
315
|
}
|
|
391
316
|
|
|
392
317
|
debug(event, ...args) {
|
|
@@ -419,26 +344,6 @@ class Kpop__ModalController extends Controller {
|
|
|
419
344
|
}
|
|
420
345
|
}
|
|
421
346
|
|
|
422
|
-
class Kpop__RedirectController extends Controller {
|
|
423
|
-
static outlets = ["kpop--frame"];
|
|
424
|
-
static values = {
|
|
425
|
-
path: String,
|
|
426
|
-
target: String,
|
|
427
|
-
};
|
|
428
|
-
|
|
429
|
-
kpopFrameOutletConnected(frame) {
|
|
430
|
-
if (this.targetValue === frame.element.id) {
|
|
431
|
-
frame.dismiss().then(() => {
|
|
432
|
-
document.getElementById(this.targetValue).src = this.pathValue;
|
|
433
|
-
});
|
|
434
|
-
} else {
|
|
435
|
-
Turbo.visit(this.pathValue, { action: "replace" });
|
|
436
|
-
}
|
|
437
|
-
|
|
438
|
-
this.element.remove();
|
|
439
|
-
}
|
|
440
|
-
}
|
|
441
|
-
|
|
442
347
|
/**
|
|
443
348
|
* Scrim controller wraps an element that creates a whole page layer.
|
|
444
349
|
* It is intended to be used behind a modal or nav drawer.
|
|
@@ -588,11 +493,97 @@ function resetStyle(element, property, previousValue) {
|
|
|
588
493
|
}
|
|
589
494
|
}
|
|
590
495
|
|
|
496
|
+
class StreamModal extends Modal {
|
|
497
|
+
constructor(id, action) {
|
|
498
|
+
super(id);
|
|
499
|
+
|
|
500
|
+
this.action = action;
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
async open() {
|
|
504
|
+
await super.open();
|
|
505
|
+
|
|
506
|
+
window.history.pushState({ kpop: true, id: this.id }, "", window.location);
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
async dismiss() {
|
|
510
|
+
await super.dismiss();
|
|
511
|
+
|
|
512
|
+
if (this.isCurrentLocation) {
|
|
513
|
+
await this.pop("popstate", () => window.history.back());
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
this.frameElement.innerHTML = "";
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
beforeVisit(frame, e) {
|
|
520
|
+
super.beforeVisit(frame, e);
|
|
521
|
+
|
|
522
|
+
e.preventDefault();
|
|
523
|
+
|
|
524
|
+
frame.dismiss({ animate: false }).then(() => {
|
|
525
|
+
Turbo.visit(e.detail.url);
|
|
526
|
+
|
|
527
|
+
this.debug("before-visit-end");
|
|
528
|
+
});
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
popstate(frame, e) {
|
|
532
|
+
super.popstate(frame, e);
|
|
533
|
+
|
|
534
|
+
frame.dismiss({ animate: true, reason: "popstate" });
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
get isCurrentLocation() {
|
|
538
|
+
return window.history.state?.kpop && window.history.state?.id === this.id;
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
class StreamRenderer {
|
|
543
|
+
constructor(frame, action) {
|
|
544
|
+
this.frame = frame;
|
|
545
|
+
this.action = action;
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
render() {
|
|
549
|
+
this.frame.src = "";
|
|
550
|
+
this.frame.innerHTML = "";
|
|
551
|
+
this.frame.append(this.action.templateContent);
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
function kpop(action) {
|
|
556
|
+
return action.targetElements[0]?.kpop;
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
Turbo.StreamActions.kpop_open = function () {
|
|
560
|
+
const animate = !kpop(this).openValue;
|
|
561
|
+
|
|
562
|
+
kpop(this)
|
|
563
|
+
?.dismiss({ animate, reason: "before-turbo-stream" })
|
|
564
|
+
.then(() => {
|
|
565
|
+
new StreamRenderer(this.targetElements[0], this).render();
|
|
566
|
+
kpop(this)?.open(new StreamModal(this.target, this), { animate });
|
|
567
|
+
});
|
|
568
|
+
};
|
|
569
|
+
|
|
570
|
+
Turbo.StreamActions.kpop_dismiss = function () {
|
|
571
|
+
kpop(this)?.dismiss({ reason: "turbo_stream.kpop.dismiss" });
|
|
572
|
+
};
|
|
573
|
+
|
|
574
|
+
Turbo.StreamActions.kpop_redirect_to = function () {
|
|
575
|
+
if (this.dataset.turboFrame === this.target) {
|
|
576
|
+
this.targetElements[0].src = this.getAttribute("href");
|
|
577
|
+
} else {
|
|
578
|
+
Turbo.visit(this.getAttribute("href"), {
|
|
579
|
+
action: this.dataset.turboAction,
|
|
580
|
+
});
|
|
581
|
+
}
|
|
582
|
+
};
|
|
583
|
+
|
|
591
584
|
const Definitions = [
|
|
592
|
-
{ identifier: "kpop--close", controllerConstructor: Kpop__CloseController },
|
|
593
585
|
{ identifier: "kpop--frame", controllerConstructor: Kpop__FrameController },
|
|
594
586
|
{ identifier: "kpop--modal", controllerConstructor: Kpop__ModalController },
|
|
595
|
-
{ identifier: "kpop--redirect", controllerConstructor: Kpop__RedirectController },
|
|
596
587
|
{ identifier: "scrim", controllerConstructor: ScrimController },
|
|
597
588
|
];
|
|
598
589
|
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{Controller as e}from"@hotwired/stimulus";import{Turbo as t}from"@hotwired/turbo-rails";class
|
|
1
|
+
import{Controller as e}from"@hotwired/stimulus";import{Turbo as t}from"@hotwired/turbo-rails";class s{constructor(e){this.id=e}async open(){this.debug("open")}async dismiss(){this.debug("dismiss")}beforeVisit(e,t){this.debug("before-visit",t.detail.url)}popstate(e,t){this.debug("popstate",t.state)}async pop(e,t){this.debug("pop");const s=new Promise((t=>{window.addEventListener(e,(()=>{t()}),{once:!0})}));return t(),s}get frameElement(){return document.getElementById(this.id)}get modalElement(){return this.frameElement?.querySelector("[data-controller*='kpop--modal']")}get currentLocationValue(){return this.modalElement?.dataset["kpop-ModalCurrentLocationValue"]||"/"}get fallbackLocationValue(){return this.modalElement?.dataset["kpop-ModalFallbackLocationValue"]||"/"}get isCurrentLocation(){return window.history.state?.turbo&&t.session.location.href===this.src}debug(e,...t){}}class i extends s{constructor(e,t=null){super(e),t&&(this.src=t)}async dismiss(){if(await super.dismiss(),this.visitStarted)this.debug("skipping dismiss, visit started");else{if(this.isCurrentLocation)return this.pop("turbo:load",(()=>{this.debug("turbo-visit",this.fallbackLocationValue),t.visit(this.fallbackLocationValue,{action:"replace"})}));this.debug("skipping dismiss, not current location")}}beforeVisit(e,t){super.beforeVisit(e,t),this.visitStarted=!0,e.scrimOutlet.hide({animate:!1})}get src(){return new URL(this.currentLocationValue.toString(),document.baseURI).toString()}}class n extends s{constructor(e,t){super(e),this.src=t}async dismiss(){await super.dismiss(),this.isCurrentLocation||this.debug("skipping dismiss, not current location"),await this.pop("turbo:load",(()=>window.history.back()))}beforeVisit(e,s){super.beforeVisit(e,s),s.preventDefault(),e.dismiss({animate:!1}).then((()=>{t.visit(s.detail.url),this.debug("before-visit-end")}))}popstate(e,t){super.popstate(e,t),e.scrimOutlet.hide({animate:!1})}}class a extends e{static outlets=["scrim"];static targets=["modal"];static values={open:Boolean};connect(){if(this.debug("connect",this.element.src),this.element.kpop=this,this.element.src&&this.element.complete)this.debug("new frame modal",this.element.src),this.open(new n(this.element.id,this.element.src),{animate:!1});else{this.element.querySelector("[data-controller*='kpop--modal']")&&(this.debug("new content modal",window.location.pathname),this.open(new i(this.element.id),{animate:!1}))}}disconnect(){this.debug("disconnect"),delete this.element.kpop,delete this.modal}scrimOutletConnected(e){this.debug("scrim-connected"),this.scrimConnected=!0,this.openValue&&e.show({animate:!1})}openValueChanged(e){this.debug("open-changed",e),this.element.parentElement.style.display=e?"flex":"none"}async open(e,{animate:t=!0}={}){return this.isOpen?(this.debug("skip open as already open"),!1):this.opening||=this.#e((()=>this.#t(e,{animate:t})))}async dismiss({animate:e=!0,reason:t=""}={}){return this.isOpen?this.dismissing||=this.#e((()=>this.#s({animate:e,reason:t}))):(this.debug("skip dismiss as already closed"),!1)}popstate(e){this.modal?.popstate(this,e)}beforeFrameRender(e){this.debug("before-frame-render",e.detail.newFrame.baseURI),e.preventDefault(),this.dismiss({animate:!0,reason:"before-frame-render"}).then((()=>{this.debug("resume-frame-render",e.detail.newFrame.baseURI),e.detail.resume()}))}beforeStreamRender(e){this.debug("before-stream-render",e.detail);const t=e.detail.render;e.detail.render=e=>{(this.dismissing||Promise.resolve()).then((()=>{this.debug("stream-render",e),t(e)}))}}beforeVisit(e){this.debug("before-visit",e.detail.url),e.detail.url!==this.element.src&&this.isOpen&&this.modal.beforeVisit(this,e)}frameLoad(e){return this.debug("frame-load"),this.open(new n(this.element.id,this.element.src),{animate:!0})}get isOpen(){return this.openValue&&!this.dismissing}async#t(e,{animate:t=!0}={}){this.debug("open-start",{animate:t});const s=this.scrimConnected&&this.scrimOutlet;this.modal=e,this.openValue=!0,await e.open({animate:t}),await(s?.show({animate:t})),delete this.opening,this.debug("open-end")}async#s({animate:e=!0,reason:t=""}={}){this.debug("dismiss-start",{animate:e,reason:t}),this.modal||console.warn("modal missing on dismiss"),await this.scrimOutlet.hide({animate:e}),await(this.modal?.dismiss()),this.openValue=!1,this.modal=null,delete this.dismissing,this.debug("dismiss-end")}async#e(e){return new Promise(window.requestAnimationFrame).then(e)}debug(e,...t){}}class o extends e{static values={open:Boolean,captive:Boolean,zIndex:Number};connect(){this.defaultZIndexValue=this.zIndexValue,this.defaultCaptiveValue=this.captiveValue,this.element.scrim=this}disconnect(){delete this.element.scrim}async show({captive:e=this.defaultCaptiveValue,zIndex:t=this.defaultZIndexValue,top:s=window.scrollY,animate:i=!0}={}){this.openValue&&await this.hide({animate:i}),this.openValue=!0,this.dispatch("show",{bubbles:!0}),this.#i(e,t,s),i&&(this.element.dataset.showAnimating="",await new Promise((e=>{this.element.addEventListener("animationend",(()=>e()),{once:!0})})),delete this.element.dataset.showAnimating)}async hide({animate:e=!0}={}){this.openValue&&!this.element.dataset.hideAnimating&&(this.dispatch("hide",{bubbles:!0}),e&&(this.element.dataset.hideAnimating="",await new Promise((e=>{this.element.addEventListener("animationend",(()=>e()),{once:!0})})),delete this.element.dataset.hideAnimating),this.#n(),this.openValue=!1)}dismiss(e){this.captiveValue||this.dispatch("dismiss",{bubbles:!0})}escape(e){"Escape"!==e.key||this.captiveValue||e.defaultPrevented||this.dispatch("dismiss",{bubbles:!0})}#i(e,t,s){this.captiveValue=e,this.zIndexValue=t,this.scrollY=s,this.previousPosition=document.body.style.position,this.previousTop=document.body.style.top,this.element.style.zIndex=this.zIndexValue,document.body.style.top=`-${s}px`,document.body.style.position="fixed"}#n(){this.captiveValue=this.defaultCaptiveValue,this.zIndexValue=this.defaultZIndexValue,r(this.element,"z-index",null),r(document.body,"position",null),r(document.body,"top",null),window.scrollTo({left:0,top:this.scrollY,behavior:"instant"}),delete this.scrollY,delete this.previousPosition,delete this.previousTop}}function r(e,t,s){s?e.style.setProperty(t,s):e.style.removeProperty(t)}class d extends s{constructor(e,t){super(e),this.action=t}async open(){await super.open(),window.history.pushState({kpop:!0,id:this.id},"",window.location)}async dismiss(){await super.dismiss(),this.isCurrentLocation&&await this.pop("popstate",(()=>window.history.back())),this.frameElement.innerHTML=""}beforeVisit(e,s){super.beforeVisit(e,s),s.preventDefault(),e.dismiss({animate:!1}).then((()=>{t.visit(s.detail.url),this.debug("before-visit-end")}))}popstate(e,t){super.popstate(e,t),e.dismiss({animate:!0,reason:"popstate"})}get isCurrentLocation(){return window.history.state?.kpop&&window.history.state?.id===this.id}}class l{constructor(e,t){this.frame=e,this.action=t}render(){this.frame.src="",this.frame.innerHTML="",this.frame.append(this.action.templateContent)}}function h(e){return e.targetElements[0]?.kpop}t.StreamActions.kpop_open=function(){const e=!h(this).openValue;h(this)?.dismiss({animate:e,reason:"before-turbo-stream"}).then((()=>{new l(this.targetElements[0],this).render(),h(this)?.open(new d(this.target,this),{animate:e})}))},t.StreamActions.kpop_dismiss=function(){h(this)?.dismiss({reason:"turbo_stream.kpop.dismiss"})},t.StreamActions.kpop_redirect_to=function(){this.dataset.turboFrame===this.target?this.targetElements[0].src=this.getAttribute("href"):t.visit(this.getAttribute("href"),{action:this.dataset.turboAction})};const u=[{identifier:"kpop--frame",controllerConstructor:a},{identifier:"kpop--modal",controllerConstructor:class extends e{static values={fallback_location:String,layout:String};connect(){this.debug("connect"),this.layoutValue&&document.querySelector("#kpop").classList.toggle(this.layoutValue,!0)}disconnect(){this.debug("disconnect"),this.layoutValue&&document.querySelector("#kpop").classList.toggle(this.layoutValue,!1)}debug(e,...t){}}},{identifier:"scrim",controllerConstructor:o}];export{u as default};
|
|
2
2
|
//# sourceMappingURL=kpop.min.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"kpop.min.js","sources":["../../../javascript/kpop/modals/modal.js","../../../javascript/kpop/modals/content_modal.js","../../../javascript/kpop/modals/frame_modal.js","../../../javascript/kpop/modals/stream_modal.js","../../../javascript/kpop/modals/stream_renderer.js","../../../javascript/kpop/controllers/frame_controller.js","../../../javascript/kpop/controllers/scrim_controller.js","../../../javascript/kpop/application.js","../../../javascript/kpop/controllers/close_controller.js","../../../javascript/kpop/controllers/modal_controller.js","../../../javascript/kpop/controllers/redirect_controller.js"],"sourcesContent":["import { Turbo } from \"@hotwired/turbo-rails\";\n\nimport DEBUG from \"../debug\";\n\nexport class Modal {\n constructor(id) {\n this.id = id;\n }\n\n async open() {\n this.debug(\"open\");\n }\n\n async dismiss() {\n this.debug(`dismiss`);\n }\n\n beforeVisit(frame, e) {\n this.debug(`before-visit`, e.detail.url);\n }\n\n popstate(frame, e) {\n this.debug(`popstate`, e.state);\n }\n\n async pop(event, callback) {\n this.debug(`pop`);\n\n const promise = new Promise((resolve) => {\n window.addEventListener(\n event,\n () => {\n resolve();\n },\n { once: true }\n );\n });\n\n callback();\n\n return promise;\n }\n\n get frameElement() {\n return document.getElementById(this.id);\n }\n\n get modalElement() {\n return this.frameElement?.querySelector(\"[data-controller*='kpop--modal']\");\n }\n\n get currentLocationValue() {\n return this.modalElement?.dataset[\"kpop-ModalCurrentLocationValue\"] || \"/\";\n }\n\n get fallbackLocationValue() {\n return this.modalElement?.dataset[\"kpop-ModalFallbackLocationValue\"] || \"/\";\n }\n\n get isCurrentLocation() {\n return (\n window.history.state?.turbo && Turbo.session.location.href === this.src\n );\n }\n\n debug(event, ...args) {\n if (DEBUG) console.debug(`${this.constructor.name}:${event}`, ...args);\n }\n}\n","import { Turbo } from \"@hotwired/turbo-rails\";\n\nimport { Modal } from \"./modal\";\n\nexport class ContentModal extends Modal {\n constructor(id, src = null) {\n super(id);\n\n if (src) this.src = src;\n }\n\n async dismiss() {\n await super.dismiss();\n\n if (this.visitStarted) {\n this.debug(\"skipping dismiss, visit started\");\n return;\n }\n if (!this.isCurrentLocation) {\n this.debug(\"skipping dismiss, not current location\");\n return;\n }\n\n return this.pop(\"turbo:load\", () => {\n this.debug(\"turbo-visit\", this.fallbackLocationValue);\n Turbo.visit(this.fallbackLocationValue, { action: \"replace\" });\n });\n\n // no specific close action required, this is turbo's responsibility\n }\n\n beforeVisit(frame, e) {\n super.beforeVisit(frame, e);\n\n this.visitStarted = true;\n\n frame.scrimOutlet.hide({ animate: false });\n }\n\n get src() {\n return new URL(\n this.currentLocationValue.toString(),\n document.baseURI\n ).toString();\n }\n}\n","import { Turbo } from \"@hotwired/turbo-rails\";\n\nimport { Modal } from \"./modal\";\n\nexport class FrameModal extends Modal {\n constructor(id, src) {\n super(id);\n this.src = src;\n }\n\n async dismiss() {\n await super.dismiss();\n\n if (!this.isCurrentLocation) {\n this.debug(\"skipping dismiss, not current location\");\n }\n\n await this.pop(\"turbo:load\", () => window.history.back());\n\n // no specific close action required, this is turbo's responsibility\n }\n\n beforeVisit(frame, e) {\n super.beforeVisit(frame, e);\n\n e.preventDefault();\n\n frame.dismiss({ animate: false }).then(() => {\n Turbo.visit(e.detail.url);\n\n this.debug(\"before-visit-end\");\n });\n }\n\n popstate(frame, e) {\n super.popstate(frame, e);\n\n // Turbo will restore modal state, but we need to reset the scrim\n frame.scrimOutlet.hide({ animate: false });\n }\n}\n","import { Turbo } from \"@hotwired/turbo-rails\";\n\nimport { Modal } from \"./modal\";\n\nexport class StreamModal extends Modal {\n constructor(id, action) {\n super(id);\n\n this.action = action;\n }\n\n async open() {\n await super.open();\n\n window.history.pushState({ kpop: true, id: this.id }, \"\", window.location);\n }\n\n async dismiss() {\n await super.dismiss();\n\n if (this.isCurrentLocation) {\n await this.pop(\"popstate\", () => window.history.back());\n }\n\n this.frameElement.innerHTML = \"\";\n }\n\n beforeVisit(frame, e) {\n super.beforeVisit(frame, e);\n\n e.preventDefault();\n\n frame.dismiss({ animate: false }).then(() => {\n Turbo.visit(e.detail.url);\n\n this.debug(\"before-visit-end\");\n });\n }\n\n popstate(frame, e) {\n super.popstate(frame, e);\n\n frame.dismiss({ animate: true, reason: \"popstate\" });\n }\n\n get isCurrentLocation() {\n return window.history.state?.kpop && window.history.state?.id === this.id;\n }\n}\n","import DEBUG from \"../debug\";\n\nexport class StreamRenderer {\n constructor(frame, action) {\n this.frame = frame;\n this.action = action;\n }\n\n render() {\n if (DEBUG) console.debug(\"stream-renderer:render\");\n this.frame.src = \"\";\n this.frame.innerHTML = \"\";\n this.frame.append(this.action.templateContent);\n }\n}\n","import { Controller } from \"@hotwired/stimulus\";\nimport { Turbo } from \"@hotwired/turbo-rails\";\n\nimport DEBUG from \"../debug\";\nimport { ContentModal } from \"../modals/content_modal\";\nimport { FrameModal } from \"../modals/frame_modal\";\nimport { StreamModal } from \"../modals/stream_modal\";\nimport { StreamRenderer } from \"../modals/stream_renderer\";\n\nTurbo.StreamActions.kpop_open = function () {\n const frame = () => {\n return this.targetElements[0];\n };\n const animate = !frame?.kpop?.openValue;\n\n frame()\n .kpop.dismiss({ animate, reason: \"before-turbo-stream\" })\n .then(() => {\n new StreamRenderer(frame(), this).render();\n frame().kpop.open(new StreamModal(this.target, this), { animate });\n });\n};\n\nexport default class Kpop__FrameController extends Controller {\n static outlets = [\"scrim\"];\n static targets = [\"modal\"];\n static values = {\n open: Boolean,\n };\n\n connect() {\n this.debug(\"connect\", this.element.src);\n\n this.element.kpop = this;\n\n // restoration visit\n if (this.element.src && this.element.complete) {\n this.debug(\"new frame modal\", this.element.src);\n this.open(new FrameModal(this.element.id, this.element.src), {\n animate: false,\n });\n } else {\n const element = this.element.querySelector(\n \"[data-controller*='kpop--modal']\"\n );\n if (element) {\n this.debug(\"new content modal\", window.location.pathname);\n this.open(new ContentModal(this.element.id), { animate: false });\n }\n }\n }\n\n disconnect() {\n this.debug(\"disconnect\");\n\n delete this.element.kpop;\n delete this.modal;\n }\n\n scrimOutletConnected(scrim) {\n this.debug(\"scrim-connected\");\n\n this.scrimConnected = true;\n\n if (this.openValue) scrim.show({ animate: false });\n }\n\n openValueChanged(open) {\n this.debug(\"open-changed\", open);\n\n this.element.parentElement.style.display = open ? \"flex\" : \"none\";\n }\n\n async open(modal, { animate = true } = {}) {\n if (this.isOpen) {\n this.debug(\"skip open as already open\");\n return false;\n }\n\n this.opening ||= this.#nextAnimationFrame(() => {\n return this.#open(modal, { animate });\n });\n\n return this.opening;\n }\n\n async dismiss({ animate = true, reason = \"\" } = {}) {\n if (!this.isOpen) {\n this.debug(\"skip dismiss as already closed\");\n return false;\n }\n\n this.dismissing ||= this.#nextAnimationFrame(() => {\n return new Promise((resolve) => {\n this.#dismiss({ animate, reason }).then(() => {\n return this.#nextAnimationFrame(resolve);\n });\n });\n });\n\n return this.dismissing;\n }\n\n // EVENTS\n\n popstate(event) {\n this.modal?.popstate(this, event);\n }\n\n beforeFrameRender(event) {\n this.debug(\"before-frame-render\", event.detail.newFrame.baseURI);\n\n event.preventDefault();\n\n this.dismiss({ animate: true, reason: \"before-frame-render\" }).then(() => {\n event.detail.resume();\n });\n }\n\n beforeVisit(e) {\n this.debug(\"before-visit\", e.detail.url);\n\n // ignore visits to the current frame, these fire when the frame navigates\n if (e.detail.url === this.element.src) return;\n\n // ignore unless we're open\n if (!this.isOpen) return;\n\n this.modal.beforeVisit(this, e);\n }\n\n frameLoad(event) {\n this.debug(\"frame-load\");\n\n return this.open(new FrameModal(this.element.id, this.element.src), {\n animate: true,\n });\n }\n\n get isOpen() {\n return this.openValue && !this.dismissing;\n }\n\n async #open(modal, { animate = true } = {}) {\n this.debug(\"open-start\", { animate });\n\n const scrim = this.scrimConnected && this.scrimOutlet;\n\n this.modal = modal;\n this.openValue = true;\n\n modal.open({ animate });\n scrim?.show({ animate });\n\n delete this.opening;\n\n this.debug(\"open-end\");\n }\n\n async #dismiss({ animate = true, reason = \"\" } = {}) {\n this.debug(\"dismiss-start\", { animate, reason });\n\n if (!this.modal) {\n console.warn(\"modal missing on dismiss\");\n if (DEBUG) debugger;\n }\n\n await this.scrimOutlet.hide({ animate });\n await this.modal?.dismiss();\n\n this.openValue = false;\n this.modal = null;\n delete this.dismissing;\n\n this.debug(\"dismiss-end\");\n }\n\n #nextAnimationFrame(callback) {\n return new Promise((resolve) => {\n window.requestAnimationFrame(() => {\n resolve(callback());\n });\n });\n }\n\n debug(event, ...args) {\n if (DEBUG) console.debug(`FrameController:${event}`, ...args);\n }\n}\n","import { Controller } from \"@hotwired/stimulus\";\n\nimport DEBUG from \"../debug\";\n\n/**\n * Scrim controller wraps an element that creates a whole page layer.\n * It is intended to be used behind a modal or nav drawer.\n *\n * If the Scrim element receives a click event, it automatically triggers \"scrim:hide\".\n *\n * You can show and hide the scrim programmatically by calling show/hide on the controller, e.g. using an outlet.\n *\n * If you need to respond to the scrim showing or hiding you should subscribe to \"scrim:show\" and \"scrim:hide\".\n */\nexport default class ScrimController extends Controller {\n static values = {\n open: Boolean,\n captive: Boolean,\n zIndex: Number,\n };\n\n connect() {\n if (DEBUG) console.debug(\"scrim:connect\");\n\n this.defaultZIndexValue = this.zIndexValue;\n this.defaultCaptiveValue = this.captiveValue;\n\n this.element.scrim = this;\n }\n\n disconnect() {\n if (DEBUG) console.debug(\"scrim:disconnect\");\n\n delete this.element.scrim;\n }\n\n async show({\n captive = this.defaultCaptiveValue,\n zIndex = this.defaultZIndexValue,\n top = window.scrollY,\n animate = true,\n } = {}) {\n if (DEBUG) console.debug(\"scrim:before-show\");\n\n // hide the scrim before opening the new one if it's already open\n if (this.openValue) {\n await this.hide({ animate });\n }\n\n // update internal state\n this.openValue = true;\n\n // notify listeners of pending request\n this.dispatch(\"show\", { bubbles: true });\n\n if (DEBUG) console.debug(\"scrim:show-start\");\n\n // update state, perform style updates\n this.#show(captive, zIndex, top);\n\n if (animate) {\n // animate opening\n // this will trigger an animationEnd event via CSS that completes the open\n this.element.dataset.showAnimating = \"\";\n\n await new Promise((resolve) => {\n this.element.addEventListener(\"animationend\", () => resolve(), {\n once: true,\n });\n });\n\n delete this.element.dataset.showAnimating;\n }\n\n if (DEBUG) console.debug(\"scrim:show-end\");\n }\n\n async hide({ animate = true } = {}) {\n if (!this.openValue || this.element.dataset.hideAnimating) return;\n\n if (DEBUG) console.debug(\"scrim:before-hide\");\n\n // notify listeners of pending request\n this.dispatch(\"hide\", { bubbles: true });\n\n if (DEBUG) console.debug(\"scrim:hide-start\");\n\n if (animate) {\n // set animation state\n // this will trigger an animationEnd event via CSS that completes the hide\n this.element.dataset.hideAnimating = \"\";\n\n await new Promise((resolve) => {\n this.element.addEventListener(\"animationend\", () => resolve(), {\n once: true,\n });\n });\n\n delete this.element.dataset.hideAnimating;\n }\n\n this.#hide();\n\n this.openValue = false;\n\n if (DEBUG) console.debug(\"scrim:hide-end\");\n }\n\n dismiss(event) {\n if (DEBUG) console.debug(\"scrim:dismiss\");\n\n if (!this.captiveValue) this.dispatch(\"dismiss\", { bubbles: true });\n }\n\n escape(event) {\n if (\n event.key === \"Escape\" &&\n !this.captiveValue &&\n !event.defaultPrevented\n ) {\n this.dispatch(\"dismiss\", { bubbles: true });\n }\n }\n\n /**\n * Clips body to viewport size and sets the z-index\n */\n #show(captive, zIndex, top) {\n this.captiveValue = captive;\n this.zIndexValue = zIndex;\n this.scrollY = top;\n\n this.previousPosition = document.body.style.position;\n this.previousTop = document.body.style.top;\n\n this.element.style.zIndex = this.zIndexValue;\n document.body.style.top = `-${top}px`;\n document.body.style.position = \"fixed\";\n }\n\n /**\n * Unclips body from viewport size and unsets the z-index\n */\n #hide() {\n this.captiveValue = this.defaultCaptiveValue;\n this.zIndexValue = this.defaultZIndexValue;\n\n resetStyle(this.element, \"z-index\", null);\n resetStyle(document.body, \"position\", null);\n resetStyle(document.body, \"top\", null);\n\n window.scrollTo({ left: 0, top: this.scrollY, behavior: \"instant\" });\n\n delete this.scrollY;\n delete this.previousPosition;\n delete this.previousTop;\n }\n}\n\nfunction resetStyle(element, property, previousValue) {\n if (previousValue) {\n element.style.setProperty(property, previousValue);\n } else {\n element.style.removeProperty(property);\n }\n}\n","import CloseController from \"../kpop/controllers/close_controller\";\nimport FrameController from \"../kpop/controllers/frame_controller\";\nimport ModalController from \"../kpop/controllers/modal_controller\";\nimport RedirectController from \"../kpop/controllers/redirect_controller\";\nimport ScrimController from \"../kpop/controllers/scrim_controller\";\n\nconst Definitions = [\n { identifier: \"kpop--close\", controllerConstructor: CloseController },\n { identifier: \"kpop--frame\", controllerConstructor: FrameController },\n { identifier: \"kpop--modal\", controllerConstructor: ModalController },\n { identifier: \"kpop--redirect\", controllerConstructor: RedirectController },\n { identifier: \"scrim\", controllerConstructor: ScrimController },\n];\n\nexport { Definitions as default };\n","import { Controller } from \"@hotwired/stimulus\";\n\nexport default class Kpop__CloseController extends Controller {\n static outlets = [\"kpop--frame\"];\n\n kpopFrameOutletConnected(frame) {\n frame.dismiss();\n }\n}\n","import { Controller } from \"@hotwired/stimulus\";\n\nimport DEBUG from \"../debug\";\n\nexport default class Kpop__ModalController extends Controller {\n static values = {\n fallback_location: String,\n layout: String,\n };\n\n connect() {\n this.debug(\"connect\");\n\n if (this.layoutValue) {\n document.querySelector(\"#kpop\").classList.toggle(this.layoutValue, true);\n }\n }\n\n disconnect() {\n this.debug(\"disconnect\");\n\n if (this.layoutValue) {\n document.querySelector(\"#kpop\").classList.toggle(this.layoutValue, false);\n }\n }\n\n debug(event, ...args) {\n if (DEBUG) console.debug(`ModalController:${event}`, ...args);\n }\n}\n","import { Controller } from \"@hotwired/stimulus\";\nimport { Turbo } from \"@hotwired/turbo-rails\";\n\nexport default class Kpop__RedirectController extends Controller {\n static outlets = [\"kpop--frame\"];\n static values = {\n path: String,\n target: String,\n };\n\n kpopFrameOutletConnected(frame) {\n if (this.targetValue === frame.element.id) {\n frame.dismiss().then(() => {\n document.getElementById(this.targetValue).src = this.pathValue;\n });\n } else {\n Turbo.visit(this.pathValue, { action: \"replace\" });\n }\n\n this.element.remove();\n }\n}\n"],"names":["Modal","constructor","id","this","open","debug","dismiss","beforeVisit","frame","e","detail","url","popstate","state","pop","event","callback","promise","Promise","resolve","window","addEventListener","once","frameElement","document","getElementById","modalElement","querySelector","currentLocationValue","dataset","fallbackLocationValue","isCurrentLocation","history","turbo","Turbo","session","location","href","src","args","ContentModal","super","visitStarted","visit","action","scrimOutlet","hide","animate","URL","toString","baseURI","FrameModal","back","preventDefault","then","StreamModal","pushState","kpop","innerHTML","reason","StreamRenderer","render","append","templateContent","StreamActions","kpop_open","targetElements","openValue","target","Kpop__FrameController","Controller","static","Boolean","connect","element","complete","pathname","disconnect","modal","scrimOutletConnected","scrim","scrimConnected","show","openValueChanged","parentElement","style","display","isOpen","opening","nextAnimationFrame","dismissing","beforeFrameRender","newFrame","resume","frameLoad","console","warn","requestAnimationFrame","ScrimController","captive","zIndex","Number","defaultZIndexValue","zIndexValue","defaultCaptiveValue","captiveValue","top","scrollY","dispatch","bubbles","showAnimating","hideAnimating","escape","key","defaultPrevented","previousPosition","body","position","previousTop","resetStyle","scrollTo","left","behavior","property","previousValue","setProperty","removeProperty","Definitions","identifier","controllerConstructor","kpopFrameOutletConnected","FrameController","fallback_location","String","layout","layoutValue","classList","toggle","path","targetValue","pathValue","remove"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"kpop.min.js","sources":["../../../javascript/kpop/modals/modal.js","../../../javascript/kpop/modals/content_modal.js","../../../javascript/kpop/modals/frame_modal.js","../../../javascript/kpop/controllers/frame_controller.js","../../../javascript/kpop/controllers/scrim_controller.js","../../../javascript/kpop/modals/stream_modal.js","../../../javascript/kpop/utils/stream_renderer.js","../../../javascript/kpop/turbo_actions.js","../../../javascript/kpop/application.js","../../../javascript/kpop/controllers/modal_controller.js"],"sourcesContent":["import { Turbo } from \"@hotwired/turbo-rails\";\n\nimport DEBUG from \"../debug\";\n\nexport class Modal {\n constructor(id) {\n this.id = id;\n }\n\n async open() {\n this.debug(\"open\");\n }\n\n async dismiss() {\n this.debug(`dismiss`);\n }\n\n beforeVisit(frame, e) {\n this.debug(`before-visit`, e.detail.url);\n }\n\n popstate(frame, e) {\n this.debug(`popstate`, e.state);\n }\n\n async pop(event, callback) {\n this.debug(`pop`);\n\n const promise = new Promise((resolve) => {\n window.addEventListener(\n event,\n () => {\n resolve();\n },\n { once: true }\n );\n });\n\n callback();\n\n return promise;\n }\n\n get frameElement() {\n return document.getElementById(this.id);\n }\n\n get modalElement() {\n return this.frameElement?.querySelector(\"[data-controller*='kpop--modal']\");\n }\n\n get currentLocationValue() {\n return this.modalElement?.dataset[\"kpop-ModalCurrentLocationValue\"] || \"/\";\n }\n\n get fallbackLocationValue() {\n return this.modalElement?.dataset[\"kpop-ModalFallbackLocationValue\"] || \"/\";\n }\n\n get isCurrentLocation() {\n return (\n window.history.state?.turbo && Turbo.session.location.href === this.src\n );\n }\n\n debug(event, ...args) {\n if (DEBUG) console.debug(`${this.constructor.name}:${event}`, ...args);\n }\n}\n","import { Turbo } from \"@hotwired/turbo-rails\";\n\nimport { Modal } from \"./modal\";\n\nexport class ContentModal extends Modal {\n constructor(id, src = null) {\n super(id);\n\n if (src) this.src = src;\n }\n\n async dismiss() {\n await super.dismiss();\n\n if (this.visitStarted) {\n this.debug(\"skipping dismiss, visit started\");\n return;\n }\n if (!this.isCurrentLocation) {\n this.debug(\"skipping dismiss, not current location\");\n return;\n }\n\n return this.pop(\"turbo:load\", () => {\n this.debug(\"turbo-visit\", this.fallbackLocationValue);\n Turbo.visit(this.fallbackLocationValue, { action: \"replace\" });\n });\n\n // no specific close action required, this is turbo's responsibility\n }\n\n beforeVisit(frame, e) {\n super.beforeVisit(frame, e);\n\n this.visitStarted = true;\n\n frame.scrimOutlet.hide({ animate: false });\n }\n\n get src() {\n return new URL(\n this.currentLocationValue.toString(),\n document.baseURI\n ).toString();\n }\n}\n","import { Turbo } from \"@hotwired/turbo-rails\";\n\nimport { Modal } from \"./modal\";\n\nexport class FrameModal extends Modal {\n constructor(id, src) {\n super(id);\n this.src = src;\n }\n\n async dismiss() {\n await super.dismiss();\n\n if (!this.isCurrentLocation) {\n this.debug(\"skipping dismiss, not current location\");\n }\n\n await this.pop(\"turbo:load\", () => window.history.back());\n\n // no specific close action required, this is turbo's responsibility\n }\n\n beforeVisit(frame, e) {\n super.beforeVisit(frame, e);\n\n e.preventDefault();\n\n frame.dismiss({ animate: false }).then(() => {\n Turbo.visit(e.detail.url);\n\n this.debug(\"before-visit-end\");\n });\n }\n\n popstate(frame, e) {\n super.popstate(frame, e);\n\n // Turbo will restore modal state, but we need to reset the scrim\n frame.scrimOutlet.hide({ animate: false });\n }\n}\n","import { Controller } from \"@hotwired/stimulus\";\n\nimport DEBUG from \"../debug\";\nimport { ContentModal } from \"../modals/content_modal\";\nimport { FrameModal } from \"../modals/frame_modal\";\n\nexport default class Kpop__FrameController extends Controller {\n static outlets = [\"scrim\"];\n static targets = [\"modal\"];\n static values = {\n open: Boolean,\n };\n\n connect() {\n this.debug(\"connect\", this.element.src);\n\n this.element.kpop = this;\n\n // restoration visit\n if (this.element.src && this.element.complete) {\n this.debug(\"new frame modal\", this.element.src);\n this.open(new FrameModal(this.element.id, this.element.src), {\n animate: false,\n });\n } else {\n const element = this.element.querySelector(\n \"[data-controller*='kpop--modal']\"\n );\n if (element) {\n this.debug(\"new content modal\", window.location.pathname);\n this.open(new ContentModal(this.element.id), { animate: false });\n }\n }\n }\n\n disconnect() {\n this.debug(\"disconnect\");\n\n delete this.element.kpop;\n delete this.modal;\n }\n\n scrimOutletConnected(scrim) {\n this.debug(\"scrim-connected\");\n\n this.scrimConnected = true;\n\n if (this.openValue) scrim.show({ animate: false });\n }\n\n openValueChanged(open) {\n this.debug(\"open-changed\", open);\n\n this.element.parentElement.style.display = open ? \"flex\" : \"none\";\n }\n\n async open(modal, { animate = true } = {}) {\n if (this.isOpen) {\n this.debug(\"skip open as already open\");\n return false;\n }\n\n return (this.opening ||= this.#nextFrame(() =>\n this.#open(modal, { animate })\n ));\n }\n\n async dismiss({ animate = true, reason = \"\" } = {}) {\n if (!this.isOpen) {\n this.debug(\"skip dismiss as already closed\");\n return false;\n }\n\n return (this.dismissing ||= this.#nextFrame(() =>\n this.#dismiss({ animate, reason })\n ));\n }\n\n // EVENTS\n\n popstate(event) {\n this.modal?.popstate(this, event);\n }\n\n beforeFrameRender(event) {\n this.debug(\"before-frame-render\", event.detail.newFrame.baseURI);\n\n event.preventDefault();\n\n this.dismiss({ animate: true, reason: \"before-frame-render\" }).then(() => {\n this.debug(\"resume-frame-render\", event.detail.newFrame.baseURI);\n event.detail.resume();\n });\n }\n\n beforeStreamRender(event) {\n this.debug(\"before-stream-render\", event.detail);\n\n const resume = event.detail.render;\n\n // Defer rendering until dismiss is complete.\n // Dismiss may change history so we need to wait for it to complete to avoid\n // losing DOM changes on restoration visits.\n event.detail.render = (stream) => {\n (this.dismissing || Promise.resolve()).then(() => {\n this.debug(\"stream-render\", stream);\n resume(stream);\n });\n };\n }\n\n beforeVisit(e) {\n this.debug(\"before-visit\", e.detail.url);\n\n // ignore visits to the current frame, these fire when the frame navigates\n if (e.detail.url === this.element.src) return;\n\n // ignore unless we're open\n if (!this.isOpen) return;\n\n this.modal.beforeVisit(this, e);\n }\n\n frameLoad(event) {\n this.debug(\"frame-load\");\n\n return this.open(new FrameModal(this.element.id, this.element.src), {\n animate: true,\n });\n }\n\n get isOpen() {\n return this.openValue && !this.dismissing;\n }\n\n async #open(modal, { animate = true } = {}) {\n this.debug(\"open-start\", { animate });\n\n const scrim = this.scrimConnected && this.scrimOutlet;\n\n this.modal = modal;\n this.openValue = true;\n\n await modal.open({ animate });\n await scrim?.show({ animate });\n\n delete this.opening;\n\n this.debug(\"open-end\");\n }\n\n async #dismiss({ animate = true, reason = \"\" } = {}) {\n this.debug(\"dismiss-start\", { animate, reason });\n\n if (!this.modal) {\n console.warn(\"modal missing on dismiss\");\n if (DEBUG) debugger;\n }\n\n await this.scrimOutlet.hide({ animate });\n await this.modal?.dismiss();\n\n this.openValue = false;\n this.modal = null;\n delete this.dismissing;\n\n this.debug(\"dismiss-end\");\n }\n\n async #nextFrame(callback) {\n // return Promise.resolve().then(callback);\n return new Promise(window.requestAnimationFrame).then(callback);\n }\n\n debug(event, ...args) {\n if (DEBUG) console.debug(`FrameController:${event}`, ...args);\n }\n}\n","import { Controller } from \"@hotwired/stimulus\";\n\nimport DEBUG from \"../debug\";\n\n/**\n * Scrim controller wraps an element that creates a whole page layer.\n * It is intended to be used behind a modal or nav drawer.\n *\n * If the Scrim element receives a click event, it automatically triggers \"scrim:hide\".\n *\n * You can show and hide the scrim programmatically by calling show/hide on the controller, e.g. using an outlet.\n *\n * If you need to respond to the scrim showing or hiding you should subscribe to \"scrim:show\" and \"scrim:hide\".\n */\nexport default class ScrimController extends Controller {\n static values = {\n open: Boolean,\n captive: Boolean,\n zIndex: Number,\n };\n\n connect() {\n if (DEBUG) console.debug(\"scrim:connect\");\n\n this.defaultZIndexValue = this.zIndexValue;\n this.defaultCaptiveValue = this.captiveValue;\n\n this.element.scrim = this;\n }\n\n disconnect() {\n if (DEBUG) console.debug(\"scrim:disconnect\");\n\n delete this.element.scrim;\n }\n\n async show({\n captive = this.defaultCaptiveValue,\n zIndex = this.defaultZIndexValue,\n top = window.scrollY,\n animate = true,\n } = {}) {\n if (DEBUG) console.debug(\"scrim:before-show\");\n\n // hide the scrim before opening the new one if it's already open\n if (this.openValue) {\n await this.hide({ animate });\n }\n\n // update internal state\n this.openValue = true;\n\n // notify listeners of pending request\n this.dispatch(\"show\", { bubbles: true });\n\n if (DEBUG) console.debug(\"scrim:show-start\");\n\n // update state, perform style updates\n this.#show(captive, zIndex, top);\n\n if (animate) {\n // animate opening\n // this will trigger an animationEnd event via CSS that completes the open\n this.element.dataset.showAnimating = \"\";\n\n await new Promise((resolve) => {\n this.element.addEventListener(\"animationend\", () => resolve(), {\n once: true,\n });\n });\n\n delete this.element.dataset.showAnimating;\n }\n\n if (DEBUG) console.debug(\"scrim:show-end\");\n }\n\n async hide({ animate = true } = {}) {\n if (!this.openValue || this.element.dataset.hideAnimating) return;\n\n if (DEBUG) console.debug(\"scrim:before-hide\");\n\n // notify listeners of pending request\n this.dispatch(\"hide\", { bubbles: true });\n\n if (DEBUG) console.debug(\"scrim:hide-start\");\n\n if (animate) {\n // set animation state\n // this will trigger an animationEnd event via CSS that completes the hide\n this.element.dataset.hideAnimating = \"\";\n\n await new Promise((resolve) => {\n this.element.addEventListener(\"animationend\", () => resolve(), {\n once: true,\n });\n });\n\n delete this.element.dataset.hideAnimating;\n }\n\n this.#hide();\n\n this.openValue = false;\n\n if (DEBUG) console.debug(\"scrim:hide-end\");\n }\n\n dismiss(event) {\n if (DEBUG) console.debug(\"scrim:dismiss\");\n\n if (!this.captiveValue) this.dispatch(\"dismiss\", { bubbles: true });\n }\n\n escape(event) {\n if (\n event.key === \"Escape\" &&\n !this.captiveValue &&\n !event.defaultPrevented\n ) {\n this.dispatch(\"dismiss\", { bubbles: true });\n }\n }\n\n /**\n * Clips body to viewport size and sets the z-index\n */\n #show(captive, zIndex, top) {\n this.captiveValue = captive;\n this.zIndexValue = zIndex;\n this.scrollY = top;\n\n this.previousPosition = document.body.style.position;\n this.previousTop = document.body.style.top;\n\n this.element.style.zIndex = this.zIndexValue;\n document.body.style.top = `-${top}px`;\n document.body.style.position = \"fixed\";\n }\n\n /**\n * Unclips body from viewport size and unsets the z-index\n */\n #hide() {\n this.captiveValue = this.defaultCaptiveValue;\n this.zIndexValue = this.defaultZIndexValue;\n\n resetStyle(this.element, \"z-index\", null);\n resetStyle(document.body, \"position\", null);\n resetStyle(document.body, \"top\", null);\n\n window.scrollTo({ left: 0, top: this.scrollY, behavior: \"instant\" });\n\n delete this.scrollY;\n delete this.previousPosition;\n delete this.previousTop;\n }\n}\n\nfunction resetStyle(element, property, previousValue) {\n if (previousValue) {\n element.style.setProperty(property, previousValue);\n } else {\n element.style.removeProperty(property);\n }\n}\n","import { Turbo } from \"@hotwired/turbo-rails\";\n\nimport { Modal } from \"./modal\";\n\nexport class StreamModal extends Modal {\n constructor(id, action) {\n super(id);\n\n this.action = action;\n }\n\n async open() {\n await super.open();\n\n window.history.pushState({ kpop: true, id: this.id }, \"\", window.location);\n }\n\n async dismiss() {\n await super.dismiss();\n\n if (this.isCurrentLocation) {\n await this.pop(\"popstate\", () => window.history.back());\n }\n\n this.frameElement.innerHTML = \"\";\n }\n\n beforeVisit(frame, e) {\n super.beforeVisit(frame, e);\n\n e.preventDefault();\n\n frame.dismiss({ animate: false }).then(() => {\n Turbo.visit(e.detail.url);\n\n this.debug(\"before-visit-end\");\n });\n }\n\n popstate(frame, e) {\n super.popstate(frame, e);\n\n frame.dismiss({ animate: true, reason: \"popstate\" });\n }\n\n get isCurrentLocation() {\n return window.history.state?.kpop && window.history.state?.id === this.id;\n }\n}\n","import DEBUG from \"../debug\";\n\nexport class StreamRenderer {\n constructor(frame, action) {\n this.frame = frame;\n this.action = action;\n }\n\n render() {\n if (DEBUG) console.debug(\"stream-renderer:render\");\n this.frame.src = \"\";\n this.frame.innerHTML = \"\";\n this.frame.append(this.action.templateContent);\n }\n}\n","import { Turbo } from \"@hotwired/turbo-rails\";\n\nimport { StreamModal } from \"./modals/stream_modal\";\nimport { StreamRenderer } from \"./utils/stream_renderer\";\n\nfunction kpop(action) {\n return action.targetElements[0]?.kpop;\n}\n\nTurbo.StreamActions.kpop_open = function () {\n const animate = !kpop(this).openValue;\n\n kpop(this)\n ?.dismiss({ animate, reason: \"before-turbo-stream\" })\n .then(() => {\n new StreamRenderer(this.targetElements[0], this).render();\n kpop(this)?.open(new StreamModal(this.target, this), { animate });\n });\n};\n\nTurbo.StreamActions.kpop_dismiss = function () {\n kpop(this)?.dismiss({ reason: \"turbo_stream.kpop.dismiss\" });\n};\n\nTurbo.StreamActions.kpop_redirect_to = function () {\n if (this.dataset.turboFrame === this.target) {\n this.targetElements[0].src = this.getAttribute(\"href\");\n } else {\n Turbo.visit(this.getAttribute(\"href\"), {\n action: this.dataset.turboAction,\n });\n }\n};\n","import FrameController from \"../kpop/controllers/frame_controller\";\nimport ModalController from \"../kpop/controllers/modal_controller\";\nimport ScrimController from \"../kpop/controllers/scrim_controller\";\n\nimport \"./turbo_actions\";\n\nconst Definitions = [\n { identifier: \"kpop--frame\", controllerConstructor: FrameController },\n { identifier: \"kpop--modal\", controllerConstructor: ModalController },\n { identifier: \"scrim\", controllerConstructor: ScrimController },\n];\n\nexport { Definitions as default };\n","import { Controller } from \"@hotwired/stimulus\";\n\nimport DEBUG from \"../debug\";\n\nexport default class Kpop__ModalController extends Controller {\n static values = {\n fallback_location: String,\n layout: String,\n };\n\n connect() {\n this.debug(\"connect\");\n\n if (this.layoutValue) {\n document.querySelector(\"#kpop\").classList.toggle(this.layoutValue, true);\n }\n }\n\n disconnect() {\n this.debug(\"disconnect\");\n\n if (this.layoutValue) {\n document.querySelector(\"#kpop\").classList.toggle(this.layoutValue, false);\n }\n }\n\n debug(event, ...args) {\n if (DEBUG) console.debug(`ModalController:${event}`, ...args);\n }\n}\n"],"names":["Modal","constructor","id","this","open","debug","dismiss","beforeVisit","frame","e","detail","url","popstate","state","pop","event","callback","promise","Promise","resolve","window","addEventListener","once","frameElement","document","getElementById","modalElement","querySelector","currentLocationValue","dataset","fallbackLocationValue","isCurrentLocation","history","turbo","Turbo","session","location","href","src","args","ContentModal","super","visitStarted","visit","action","scrimOutlet","hide","animate","URL","toString","baseURI","FrameModal","back","preventDefault","then","Kpop__FrameController","Controller","static","Boolean","connect","element","kpop","complete","pathname","disconnect","modal","scrimOutletConnected","scrim","scrimConnected","openValue","show","openValueChanged","parentElement","style","display","isOpen","opening","nextFrame","reason","dismissing","beforeFrameRender","newFrame","resume","beforeStreamRender","render","stream","frameLoad","console","warn","requestAnimationFrame","ScrimController","captive","zIndex","Number","defaultZIndexValue","zIndexValue","defaultCaptiveValue","captiveValue","top","scrollY","dispatch","bubbles","showAnimating","hideAnimating","escape","key","defaultPrevented","previousPosition","body","position","previousTop","resetStyle","scrollTo","left","behavior","property","previousValue","setProperty","removeProperty","StreamModal","pushState","innerHTML","StreamRenderer","append","templateContent","targetElements","StreamActions","kpop_open","target","kpop_dismiss","kpop_redirect_to","turboFrame","getAttribute","turboAction","Definitions","identifier","controllerConstructor","FrameController","fallback_location","String","layout","layoutValue","classList","toggle"],"mappings":"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"}
|
|
@@ -12,6 +12,7 @@ module Kpop
|
|
|
12
12
|
scrim:dismiss@window->kpop--frame#dismiss
|
|
13
13
|
scrim:hide@window->kpop--frame#dismiss
|
|
14
14
|
turbo:before-frame-render->kpop--frame#beforeFrameRender
|
|
15
|
+
turbo:before-stream-render@window->kpop--frame#beforeStreamRender
|
|
15
16
|
turbo:before-visit@window->kpop--frame#beforeVisit
|
|
16
17
|
turbo:frame-load->kpop--frame#frameLoad
|
|
17
18
|
].freeze
|
|
@@ -1,14 +1,12 @@
|
|
|
1
|
-
import CloseController from "../kpop/controllers/close_controller";
|
|
2
1
|
import FrameController from "../kpop/controllers/frame_controller";
|
|
3
2
|
import ModalController from "../kpop/controllers/modal_controller";
|
|
4
|
-
import RedirectController from "../kpop/controllers/redirect_controller";
|
|
5
3
|
import ScrimController from "../kpop/controllers/scrim_controller";
|
|
6
4
|
|
|
5
|
+
import "./turbo_actions";
|
|
6
|
+
|
|
7
7
|
const Definitions = [
|
|
8
|
-
{ identifier: "kpop--close", controllerConstructor: CloseController },
|
|
9
8
|
{ identifier: "kpop--frame", controllerConstructor: FrameController },
|
|
10
9
|
{ identifier: "kpop--modal", controllerConstructor: ModalController },
|
|
11
|
-
{ identifier: "kpop--redirect", controllerConstructor: RedirectController },
|
|
12
10
|
{ identifier: "scrim", controllerConstructor: ScrimController },
|
|
13
11
|
];
|
|
14
12
|
|
|
@@ -1,25 +1,8 @@
|
|
|
1
1
|
import { Controller } from "@hotwired/stimulus";
|
|
2
|
-
import { Turbo } from "@hotwired/turbo-rails";
|
|
3
2
|
|
|
4
3
|
import DEBUG from "../debug";
|
|
5
4
|
import { ContentModal } from "../modals/content_modal";
|
|
6
5
|
import { FrameModal } from "../modals/frame_modal";
|
|
7
|
-
import { StreamModal } from "../modals/stream_modal";
|
|
8
|
-
import { StreamRenderer } from "../modals/stream_renderer";
|
|
9
|
-
|
|
10
|
-
Turbo.StreamActions.kpop_open = function () {
|
|
11
|
-
const frame = () => {
|
|
12
|
-
return this.targetElements[0];
|
|
13
|
-
};
|
|
14
|
-
const animate = !frame?.kpop?.openValue;
|
|
15
|
-
|
|
16
|
-
frame()
|
|
17
|
-
.kpop.dismiss({ animate, reason: "before-turbo-stream" })
|
|
18
|
-
.then(() => {
|
|
19
|
-
new StreamRenderer(frame(), this).render();
|
|
20
|
-
frame().kpop.open(new StreamModal(this.target, this), { animate });
|
|
21
|
-
});
|
|
22
|
-
};
|
|
23
6
|
|
|
24
7
|
export default class Kpop__FrameController extends Controller {
|
|
25
8
|
static outlets = ["scrim"];
|
|
@@ -77,11 +60,9 @@ export default class Kpop__FrameController extends Controller {
|
|
|
77
60
|
return false;
|
|
78
61
|
}
|
|
79
62
|
|
|
80
|
-
this.opening ||= this.#
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
return this.opening;
|
|
63
|
+
return (this.opening ||= this.#nextFrame(() =>
|
|
64
|
+
this.#open(modal, { animate })
|
|
65
|
+
));
|
|
85
66
|
}
|
|
86
67
|
|
|
87
68
|
async dismiss({ animate = true, reason = "" } = {}) {
|
|
@@ -90,15 +71,9 @@ export default class Kpop__FrameController extends Controller {
|
|
|
90
71
|
return false;
|
|
91
72
|
}
|
|
92
73
|
|
|
93
|
-
this.dismissing ||= this.#
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
return this.#nextAnimationFrame(resolve);
|
|
97
|
-
});
|
|
98
|
-
});
|
|
99
|
-
});
|
|
100
|
-
|
|
101
|
-
return this.dismissing;
|
|
74
|
+
return (this.dismissing ||= this.#nextFrame(() =>
|
|
75
|
+
this.#dismiss({ animate, reason })
|
|
76
|
+
));
|
|
102
77
|
}
|
|
103
78
|
|
|
104
79
|
// EVENTS
|
|
@@ -113,10 +88,27 @@ export default class Kpop__FrameController extends Controller {
|
|
|
113
88
|
event.preventDefault();
|
|
114
89
|
|
|
115
90
|
this.dismiss({ animate: true, reason: "before-frame-render" }).then(() => {
|
|
91
|
+
this.debug("resume-frame-render", event.detail.newFrame.baseURI);
|
|
116
92
|
event.detail.resume();
|
|
117
93
|
});
|
|
118
94
|
}
|
|
119
95
|
|
|
96
|
+
beforeStreamRender(event) {
|
|
97
|
+
this.debug("before-stream-render", event.detail);
|
|
98
|
+
|
|
99
|
+
const resume = event.detail.render;
|
|
100
|
+
|
|
101
|
+
// Defer rendering until dismiss is complete.
|
|
102
|
+
// Dismiss may change history so we need to wait for it to complete to avoid
|
|
103
|
+
// losing DOM changes on restoration visits.
|
|
104
|
+
event.detail.render = (stream) => {
|
|
105
|
+
(this.dismissing || Promise.resolve()).then(() => {
|
|
106
|
+
this.debug("stream-render", stream);
|
|
107
|
+
resume(stream);
|
|
108
|
+
});
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
|
|
120
112
|
beforeVisit(e) {
|
|
121
113
|
this.debug("before-visit", e.detail.url);
|
|
122
114
|
|
|
@@ -149,8 +141,8 @@ export default class Kpop__FrameController extends Controller {
|
|
|
149
141
|
this.modal = modal;
|
|
150
142
|
this.openValue = true;
|
|
151
143
|
|
|
152
|
-
modal.open({ animate });
|
|
153
|
-
scrim?.show({ animate });
|
|
144
|
+
await modal.open({ animate });
|
|
145
|
+
await scrim?.show({ animate });
|
|
154
146
|
|
|
155
147
|
delete this.opening;
|
|
156
148
|
|
|
@@ -175,12 +167,9 @@ export default class Kpop__FrameController extends Controller {
|
|
|
175
167
|
this.debug("dismiss-end");
|
|
176
168
|
}
|
|
177
169
|
|
|
178
|
-
#
|
|
179
|
-
return
|
|
180
|
-
|
|
181
|
-
resolve(callback());
|
|
182
|
-
});
|
|
183
|
-
});
|
|
170
|
+
async #nextFrame(callback) {
|
|
171
|
+
// return Promise.resolve().then(callback);
|
|
172
|
+
return new Promise(window.requestAnimationFrame).then(callback);
|
|
184
173
|
}
|
|
185
174
|
|
|
186
175
|
debug(event, ...args) {
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { Turbo } from "@hotwired/turbo-rails";
|
|
2
|
+
|
|
3
|
+
import { StreamModal } from "./modals/stream_modal";
|
|
4
|
+
import { StreamRenderer } from "./utils/stream_renderer";
|
|
5
|
+
|
|
6
|
+
function kpop(action) {
|
|
7
|
+
return action.targetElements[0]?.kpop;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
Turbo.StreamActions.kpop_open = function () {
|
|
11
|
+
const animate = !kpop(this).openValue;
|
|
12
|
+
|
|
13
|
+
kpop(this)
|
|
14
|
+
?.dismiss({ animate, reason: "before-turbo-stream" })
|
|
15
|
+
.then(() => {
|
|
16
|
+
new StreamRenderer(this.targetElements[0], this).render();
|
|
17
|
+
kpop(this)?.open(new StreamModal(this.target, this), { animate });
|
|
18
|
+
});
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
Turbo.StreamActions.kpop_dismiss = function () {
|
|
22
|
+
kpop(this)?.dismiss({ reason: "turbo_stream.kpop.dismiss" });
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
Turbo.StreamActions.kpop_redirect_to = function () {
|
|
26
|
+
if (this.dataset.turboFrame === this.target) {
|
|
27
|
+
this.targetElements[0].src = this.getAttribute("href");
|
|
28
|
+
} else {
|
|
29
|
+
Turbo.visit(this.getAttribute("href"), {
|
|
30
|
+
action: this.dataset.turboAction,
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
};
|
|
@@ -6,7 +6,6 @@ require "katalyst/kpop/matchers/capybara_parser"
|
|
|
6
6
|
require "katalyst/kpop/matchers/chained_matcher"
|
|
7
7
|
require "katalyst/kpop/matchers/frame_matcher"
|
|
8
8
|
require "katalyst/kpop/matchers/modal_matcher"
|
|
9
|
-
require "katalyst/kpop/matchers/redirect_finder"
|
|
10
9
|
require "katalyst/kpop/matchers/redirect_matcher"
|
|
11
10
|
require "katalyst/kpop/matchers/response_matcher"
|
|
12
11
|
require "katalyst/kpop/matchers/stream_matcher"
|
|
@@ -22,7 +21,9 @@ module Katalyst
|
|
|
22
21
|
# @example
|
|
23
22
|
# expect(response).to kpop_dismiss
|
|
24
23
|
def kpop_dismiss(id: "kpop")
|
|
25
|
-
ChainedMatcher.new(ResponseMatcher,
|
|
24
|
+
ChainedMatcher.new(ResponseMatcher,
|
|
25
|
+
CapybaraParser,
|
|
26
|
+
StreamMatcher.new(id:, action: "kpop_dismiss"))
|
|
26
27
|
end
|
|
27
28
|
|
|
28
29
|
# @api public
|
|
@@ -36,8 +37,7 @@ module Katalyst
|
|
|
36
37
|
|
|
37
38
|
ChainedMatcher.new(ResponseMatcher,
|
|
38
39
|
CapybaraParser,
|
|
39
|
-
StreamMatcher.new(id:, action: "
|
|
40
|
-
RedirectFinder,
|
|
40
|
+
StreamMatcher.new(id:, action: "kpop_redirect_to"),
|
|
41
41
|
RedirectMatcher.new(target))
|
|
42
42
|
end
|
|
43
43
|
|
data/lib/katalyst/kpop/turbo.rb
CHANGED
|
@@ -6,7 +6,7 @@ module Katalyst
|
|
|
6
6
|
module Kpop
|
|
7
7
|
module Turbo
|
|
8
8
|
class TagBuilder
|
|
9
|
-
delegate :action, :
|
|
9
|
+
delegate :action, :turbo_stream_action_tag, to: :@builder
|
|
10
10
|
|
|
11
11
|
def initialize(builder)
|
|
12
12
|
@builder = builder
|
|
@@ -24,31 +24,25 @@ module Katalyst
|
|
|
24
24
|
# <% end %>
|
|
25
25
|
# <% end %>
|
|
26
26
|
def open(content = nil, id: "kpop", **, &)
|
|
27
|
-
|
|
27
|
+
action(:kpop_open, id, content, **, &)
|
|
28
28
|
end
|
|
29
29
|
|
|
30
30
|
# Render a turbo stream action that will dismiss any open kpop modal.
|
|
31
31
|
def dismiss(id: "kpop")
|
|
32
|
-
|
|
33
|
-
tag.div("", data: {
|
|
34
|
-
controller: "kpop--close",
|
|
35
|
-
kpop__close_kpop__frame_outlet: "##{id}",
|
|
36
|
-
turbo_temporary: "",
|
|
37
|
-
})
|
|
38
|
-
end
|
|
32
|
+
turbo_stream_action_tag(:kpop_dismiss, target: id)
|
|
39
33
|
end
|
|
40
34
|
|
|
41
35
|
# Renders a kpop redirect controller response that will escape the frame and navigate to the given URL.
|
|
42
|
-
def redirect_to(
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
36
|
+
def redirect_to(href, id: "kpop", action: "replace", target: nil)
|
|
37
|
+
turbo_stream_action_tag(
|
|
38
|
+
:kpop_redirect_to,
|
|
39
|
+
target: id,
|
|
40
|
+
href:,
|
|
41
|
+
data: {
|
|
42
|
+
turbo_action: action,
|
|
43
|
+
turbo_frame: target,
|
|
44
|
+
},
|
|
45
|
+
)
|
|
52
46
|
end
|
|
53
47
|
end
|
|
54
48
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: katalyst-kpop
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 3.0.0.beta.
|
|
4
|
+
version: 3.0.0.beta.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Katalyst Interactive
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2023-10-
|
|
11
|
+
date: 2023-10-27 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: html-attributes-utils
|
|
@@ -82,17 +82,16 @@ files:
|
|
|
82
82
|
- app/components/scrim_component.rb
|
|
83
83
|
- app/helpers/kpop_helper.rb
|
|
84
84
|
- app/javascript/kpop/application.js
|
|
85
|
-
- app/javascript/kpop/controllers/close_controller.js
|
|
86
85
|
- app/javascript/kpop/controllers/frame_controller.js
|
|
87
86
|
- app/javascript/kpop/controllers/modal_controller.js
|
|
88
|
-
- app/javascript/kpop/controllers/redirect_controller.js
|
|
89
87
|
- app/javascript/kpop/controllers/scrim_controller.js
|
|
90
88
|
- app/javascript/kpop/debug.js
|
|
91
89
|
- app/javascript/kpop/modals/content_modal.js
|
|
92
90
|
- app/javascript/kpop/modals/frame_modal.js
|
|
93
91
|
- app/javascript/kpop/modals/modal.js
|
|
94
92
|
- app/javascript/kpop/modals/stream_modal.js
|
|
95
|
-
- app/javascript/kpop/
|
|
93
|
+
- app/javascript/kpop/turbo_actions.js
|
|
94
|
+
- app/javascript/kpop/utils/stream_renderer.js
|
|
96
95
|
- app/views/layouts/kpop.html.erb
|
|
97
96
|
- config/importmap.rb
|
|
98
97
|
- config/routes.rb
|
|
@@ -105,7 +104,6 @@ files:
|
|
|
105
104
|
- lib/katalyst/kpop/matchers/chained_matcher.rb
|
|
106
105
|
- lib/katalyst/kpop/matchers/frame_matcher.rb
|
|
107
106
|
- lib/katalyst/kpop/matchers/modal_matcher.rb
|
|
108
|
-
- lib/katalyst/kpop/matchers/redirect_finder.rb
|
|
109
107
|
- lib/katalyst/kpop/matchers/redirect_matcher.rb
|
|
110
108
|
- lib/katalyst/kpop/matchers/response_matcher.rb
|
|
111
109
|
- lib/katalyst/kpop/matchers/stream_matcher.rb
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import { Controller } from "@hotwired/stimulus";
|
|
2
|
-
import { Turbo } from "@hotwired/turbo-rails";
|
|
3
|
-
|
|
4
|
-
export default class Kpop__RedirectController extends Controller {
|
|
5
|
-
static outlets = ["kpop--frame"];
|
|
6
|
-
static values = {
|
|
7
|
-
path: String,
|
|
8
|
-
target: String,
|
|
9
|
-
};
|
|
10
|
-
|
|
11
|
-
kpopFrameOutletConnected(frame) {
|
|
12
|
-
if (this.targetValue === frame.element.id) {
|
|
13
|
-
frame.dismiss().then(() => {
|
|
14
|
-
document.getElementById(this.targetValue).src = this.pathValue;
|
|
15
|
-
});
|
|
16
|
-
} else {
|
|
17
|
-
Turbo.visit(this.pathValue, { action: "replace" });
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
this.element.remove();
|
|
21
|
-
}
|
|
22
|
-
}
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require "katalyst/kpop/matchers/capybara_matcher"
|
|
4
|
-
|
|
5
|
-
module Katalyst
|
|
6
|
-
module Kpop
|
|
7
|
-
module Matchers
|
|
8
|
-
# @api private
|
|
9
|
-
class RedirectFinder < CapybaraMatcher
|
|
10
|
-
def initialize
|
|
11
|
-
super("[data-controller='kpop--redirect']")
|
|
12
|
-
end
|
|
13
|
-
end
|
|
14
|
-
end
|
|
15
|
-
end
|
|
16
|
-
end
|
|
File without changes
|