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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5d657aa583bbc374ac12276e50d9d11d85801d6ddf1518cacaeba453893fb0be
4
- data.tar.gz: 19e213e9b618fb117e8e07ebeb1a5677daa8528f80de07d2f6ff611a208b5b8d
3
+ metadata.gz: bdd0521dfd00d4dc6d5c4f6b705d45fdcf0fa06b3a47cd6ec1b271b08b77e64a
4
+ data.tar.gz: 6a5480d57130797edd0e59e0e44710cd931033fcdbf01d286009e2be5bf8a5d6
5
5
  SHA512:
6
- metadata.gz: 5bbacf659d0a520fa43115cf376bcf1f3c58aa64b619c183fcfcb4554a42868b3d2bcbf160a92d42061e9afd1d9339be6f9598d694e57a403840d78a5cb8699c
7
- data.tar.gz: ba50a3724ddddb3b95c13918e93ae5dcf590f555da584f83276b218c8b747dc897a6f5d7bcf25015c6f16753f6a60c5b366cd843251f0668dd1c540ef0132ea6
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.#nextAnimationFrame(() => {
288
- return this.#open(modal, { animate });
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.#nextAnimationFrame(() => {
301
- return new Promise((resolve) => {
302
- this.#dismiss({ animate, reason }).then(() => {
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
- #nextAnimationFrame(callback) {
385
- return new Promise((resolve) => {
386
- window.requestAnimationFrame(() => {
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.#nextAnimationFrame(() => {
288
- return this.#open(modal, { animate });
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.#nextAnimationFrame(() => {
301
- return new Promise((resolve) => {
302
- this.#dismiss({ animate, reason }).then(() => {
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
- #nextAnimationFrame(callback) {
385
- return new Promise((resolve) => {
386
- window.requestAnimationFrame(() => {
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 i{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 i=new Promise((t=>{window.addEventListener(e,(()=>{t()}),{once:!0})}));return t(),i}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 s extends i{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 i{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,i){super.beforeVisit(e,i),i.preventDefault(),e.dismiss({animate:!1}).then((()=>{t.visit(i.detail.url),this.debug("before-visit-end")}))}popstate(e,t){super.popstate(e,t),e.scrimOutlet.hide({animate:!1})}}class a extends i{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,i){super.beforeVisit(e,i),i.preventDefault(),e.dismiss({animate:!1}).then((()=>{t.visit(i.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 o{constructor(e,t){this.frame=e,this.action=t}render(){this.frame.src="",this.frame.innerHTML="",this.frame.append(this.action.templateContent)}}t.StreamActions.kpop_open=function(){const e=()=>this.targetElements[0],t=!e?.kpop?.openValue;e().kpop.dismiss({animate:t,reason:"before-turbo-stream"}).then((()=>{new o(e(),this).render(),e().kpop.open(new a(this.target,this),{animate:t})}))};class r 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 s(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}))),this.opening)}async dismiss({animate:e=!0,reason:t=""}={}){return this.isOpen?(this.dismissing||=this.#e((()=>new Promise((i=>{this.#i({animate:e,reason:t}).then((()=>this.#e(i)))})))),this.dismissing):(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((()=>{e.detail.resume()}))}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 i=this.scrimConnected&&this.scrimOutlet;this.modal=e,this.openValue=!0,e.open({animate:t}),i?.show({animate:t}),delete this.opening,this.debug("open-end")}async#i({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")}#e(e){return new Promise((t=>{window.requestAnimationFrame((()=>{t(e())}))}))}debug(e,...t){}}class l 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:i=window.scrollY,animate:s=!0}={}){this.openValue&&await this.hide({animate:s}),this.openValue=!0,this.dispatch("show",{bubbles:!0}),this.#s(e,t,i),s&&(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})}#s(e,t,i){this.captiveValue=e,this.zIndexValue=t,this.scrollY=i,this.previousPosition=document.body.style.position,this.previousTop=document.body.style.top,this.element.style.zIndex=this.zIndexValue,document.body.style.top=`-${i}px`,document.body.style.position="fixed"}#n(){this.captiveValue=this.defaultCaptiveValue,this.zIndexValue=this.defaultZIndexValue,d(this.element,"z-index",null),d(document.body,"position",null),d(document.body,"top",null),window.scrollTo({left:0,top:this.scrollY,behavior:"instant"}),delete this.scrollY,delete this.previousPosition,delete this.previousTop}}function d(e,t,i){i?e.style.setProperty(t,i):e.style.removeProperty(t)}const h=[{identifier:"kpop--close",controllerConstructor:class extends e{static outlets=["kpop--frame"];kpopFrameOutletConnected(e){e.dismiss()}}},{identifier:"kpop--frame",controllerConstructor:r},{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:"kpop--redirect",controllerConstructor:class extends e{static outlets=["kpop--frame"];static values={path:String,target:String};kpopFrameOutletConnected(e){this.targetValue===e.element.id?e.dismiss().then((()=>{document.getElementById(this.targetValue).src=this.pathValue})):t.visit(this.pathValue,{action:"replace"}),this.element.remove()}}},{identifier:"scrim",controllerConstructor:l}];export{h as default};
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.#nextAnimationFrame(() => {
81
- return this.#open(modal, { animate });
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.#nextAnimationFrame(() => {
94
- return new Promise((resolve) => {
95
- this.#dismiss({ animate, reason }).then(() => {
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
- #nextAnimationFrame(callback) {
179
- return new Promise((resolve) => {
180
- window.requestAnimationFrame(() => {
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
+ };
@@ -8,7 +8,7 @@ module Katalyst
8
8
  # @api private
9
9
  class RedirectMatcher < Base
10
10
  def match(expected, actual)
11
- actual["data-kpop--redirect-path-value"].to_s.match?(expected)
11
+ actual["href"].to_s.match?(expected)
12
12
  end
13
13
 
14
14
  def description
@@ -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, CapybaraParser, StreamMatcher.new(id:, action: "append"))
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: "append"),
40
- RedirectFinder,
40
+ StreamMatcher.new(id:, action: "kpop_redirect_to"),
41
41
  RedirectMatcher.new(target))
42
42
  end
43
43
 
@@ -6,7 +6,7 @@ module Katalyst
6
6
  module Kpop
7
7
  module Turbo
8
8
  class TagBuilder
9
- delegate :action, :append, :tag, to: :@builder
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
- @builder.action(:kpop_open, id, content, **, &)
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
- append(id) do
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(url, id: "kpop", target: nil)
43
- append(id) do
44
- tag.div("", data: {
45
- controller: "kpop--redirect",
46
- kpop__redirect_kpop__frame_outlet: "##{id}",
47
- kpop__redirect_path_value: url,
48
- kpop__redirect_target_value: target,
49
- turbo_temporary: "",
50
- })
51
- end
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
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Katalyst
4
4
  module Kpop
5
- VERSION = "3.0.0.beta.1"
5
+ VERSION = "3.0.0.beta.2"
6
6
  end
7
7
  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.1
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-26 00:00:00.000000000 Z
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/modals/stream_renderer.js
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,9 +0,0 @@
1
- import { Controller } from "@hotwired/stimulus";
2
-
3
- export default class Kpop__CloseController extends Controller {
4
- static outlets = ["kpop--frame"];
5
-
6
- kpopFrameOutletConnected(frame) {
7
- frame.dismiss();
8
- }
9
- }
@@ -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