cubing 0.29.1 → 0.30.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (113) hide show
  1. package/README.md +1 -6
  2. package/dist/esm/.DS_Store +0 -0
  3. package/dist/esm/alg/index.js +1 -2
  4. package/dist/esm/bluetooth/index.js +36 -32
  5. package/dist/esm/bluetooth/index.js.map +2 -2
  6. package/dist/esm/{chunk-XRZBPKES.js → chunk-35OK6TQ4.js} +328 -66
  7. package/dist/esm/chunk-35OK6TQ4.js.map +7 -0
  8. package/dist/esm/{chunk-WYKXX2XY.js → chunk-4QZRHN6S.js} +10 -8
  9. package/dist/esm/{chunk-WYKXX2XY.js.map → chunk-4QZRHN6S.js.map} +2 -2
  10. package/dist/esm/{chunk-2JDBIQSV.js → chunk-5OQ34D3X.js} +7 -7
  11. package/dist/esm/{chunk-2JDBIQSV.js.map → chunk-5OQ34D3X.js.map} +2 -2
  12. package/dist/esm/{chunk-U2ONHTIX.js → chunk-6FB2XWAK.js} +33 -31
  13. package/dist/esm/chunk-6FB2XWAK.js.map +7 -0
  14. package/dist/esm/{chunk-ZNAYJGVL.js → chunk-C6KMV2PL.js} +2 -2
  15. package/dist/esm/{chunk-ZNAYJGVL.js.map → chunk-C6KMV2PL.js.map} +0 -0
  16. package/dist/esm/{chunk-XU5ILFX5.js → chunk-GQBRF4EM.js} +6 -4
  17. package/dist/esm/{chunk-XU5ILFX5.js.map → chunk-GQBRF4EM.js.map} +2 -2
  18. package/dist/esm/{chunk-WXCNEGW3.js → chunk-HR5D6SD4.js} +2 -2
  19. package/dist/esm/{chunk-WXCNEGW3.js.map → chunk-HR5D6SD4.js.map} +2 -2
  20. package/dist/esm/{chunk-XT3R2ENM.js → chunk-KOAJIBEX.js} +47 -38
  21. package/dist/esm/chunk-KOAJIBEX.js.map +7 -0
  22. package/dist/esm/{chunk-OX6O2ZO5.js → chunk-QHWK5RXN.js} +1 -1
  23. package/dist/esm/chunk-QHWK5RXN.js.map +7 -0
  24. package/dist/esm/{chunk-GW4FGG42.js → chunk-RI2DAEY6.js} +2 -2
  25. package/dist/esm/{chunk-GW4FGG42.js.map → chunk-RI2DAEY6.js.map} +0 -0
  26. package/dist/esm/{chunk-AHEXXC6V.js → chunk-VIUWS2PX.js} +4 -4
  27. package/dist/esm/chunk-VIUWS2PX.js.map +7 -0
  28. package/dist/esm/{chunk-2IZUSAXQ.js → chunk-WEYPAZEE.js} +1 -1
  29. package/dist/esm/{chunk-2IZUSAXQ.js.map → chunk-WEYPAZEE.js.map} +1 -1
  30. package/dist/esm/{chunk-NI7U4XAZ.js → chunk-ZQT3QSWD.js} +226 -113
  31. package/dist/esm/chunk-ZQT3QSWD.js.map +7 -0
  32. package/dist/esm/kpuzzle/index.js +2 -3
  33. package/dist/esm/notation/index.js +2 -3
  34. package/dist/esm/protocol/index.js +4 -5
  35. package/dist/esm/puzzle-geometry/index.js +110 -85
  36. package/dist/esm/puzzle-geometry/index.js.map +2 -2
  37. package/dist/esm/puzzles/index.js +10 -7
  38. package/dist/esm/{puzzles-dynamic-3x3x3-KIG5A6QR.js → puzzles-dynamic-3x3x3-ZKMODX2P.js} +1 -3
  39. package/dist/esm/{puzzles-dynamic-3x3x3-KIG5A6QR.js.map → puzzles-dynamic-3x3x3-ZKMODX2P.js.map} +1 -1
  40. package/dist/esm/{puzzles-dynamic-4x4x4-PEDAPUZK.js → puzzles-dynamic-4x4x4-DT42HVIY.js} +1 -3
  41. package/dist/esm/{puzzles-dynamic-4x4x4-PEDAPUZK.js.map → puzzles-dynamic-4x4x4-DT42HVIY.js.map} +1 -1
  42. package/dist/esm/{puzzles-dynamic-side-events-5C7LMBWX.js → puzzles-dynamic-side-events-HMUBMHA5.js} +2 -4
  43. package/dist/esm/{puzzles-dynamic-side-events-5C7LMBWX.js.map → puzzles-dynamic-side-events-HMUBMHA5.js.map} +2 -2
  44. package/dist/esm/{puzzles-dynamic-unofficial-WWJ4NJMX.js → puzzles-dynamic-unofficial-QXSDLTK5.js} +1 -3
  45. package/dist/esm/{puzzles-dynamic-unofficial-WWJ4NJMX.js.map → puzzles-dynamic-unofficial-QXSDLTK5.js.map} +1 -1
  46. package/dist/esm/scramble/index.js +3 -4
  47. package/dist/esm/search/index.js +8 -9
  48. package/dist/esm/{search-dynamic-sgs-side-events-4H3X5HLH.js → search-dynamic-sgs-side-events-XNTCWRI4.js} +6 -7
  49. package/dist/esm/search-dynamic-sgs-side-events-XNTCWRI4.js.map +7 -0
  50. package/dist/esm/{search-dynamic-sgs-unofficial-7IRW4LVD.js → search-dynamic-sgs-unofficial-5KMZ747E.js} +122 -68
  51. package/dist/esm/search-dynamic-sgs-unofficial-5KMZ747E.js.map +7 -0
  52. package/dist/esm/{search-dynamic-solve-3x3x3-7XZTYQMO.js → search-dynamic-solve-3x3x3-TSXPWENP.js} +649 -407
  53. package/dist/esm/search-dynamic-solve-3x3x3-TSXPWENP.js.map +7 -0
  54. package/dist/esm/{search-dynamic-solve-4x4x4-7JTJCCSY.js → search-dynamic-solve-4x4x4-FKQ2JWK2.js} +399 -151
  55. package/dist/esm/search-dynamic-solve-4x4x4-FKQ2JWK2.js.map +7 -0
  56. package/dist/esm/{search-dynamic-solve-fto-4LI23P6K.js → search-dynamic-solve-fto-GPLW7S5F.js} +74 -35
  57. package/dist/esm/search-dynamic-solve-fto-GPLW7S5F.js.map +7 -0
  58. package/dist/esm/{search-dynamic-solve-kilominx-3HEVQ4MC.js → search-dynamic-solve-kilominx-HB2QFUGF.js} +136 -72
  59. package/dist/esm/search-dynamic-solve-kilominx-HB2QFUGF.js.map +7 -0
  60. package/dist/esm/{search-dynamic-solve-master_tetraminx-UB32C7MM.js → search-dynamic-solve-master_tetraminx-LR3LJI7O.js} +84 -42
  61. package/dist/esm/search-dynamic-solve-master_tetraminx-LR3LJI7O.js.map +7 -0
  62. package/dist/esm/{search-dynamic-solve-sq1-HA72TYF2.js → search-dynamic-solve-sq1-W33UXTDZ.js} +129 -55
  63. package/dist/esm/search-dynamic-solve-sq1-W33UXTDZ.js.map +7 -0
  64. package/dist/esm/search-worker-inside-generated-string-5HKZNHKK.js +3884 -0
  65. package/dist/esm/search-worker-inside-generated-string-5HKZNHKK.js.map +7 -0
  66. package/dist/esm/{search-worker-js-entry-T6YIT7YD.js → search-worker-js-entry-PDXEE46R.js} +44 -36
  67. package/dist/esm/search-worker-js-entry-PDXEE46R.js.map +7 -0
  68. package/dist/esm/{search-worker-ts-entry-OUEC4L5I.js → search-worker-ts-entry-UV2RY2EY.js} +3 -4
  69. package/dist/esm/{search-worker-ts-entry-OUEC4L5I.js.map → search-worker-ts-entry-UV2RY2EY.js.map} +1 -1
  70. package/dist/esm/stream/index.js +1 -2
  71. package/dist/esm/stream/index.js.map +2 -2
  72. package/dist/esm/twisty/index.js +368 -300
  73. package/dist/esm/twisty/index.js.map +3 -3
  74. package/dist/esm/{twisty-dynamic-3d-AZUSXQ5S.js → twisty-dynamic-3d-GPF6TW32.js} +57 -60
  75. package/dist/esm/twisty-dynamic-3d-GPF6TW32.js.map +7 -0
  76. package/dist/types/{Alg-137fb0d5.d.ts → Alg-1c8c3757.d.ts} +25 -26
  77. package/dist/types/{KState-a73111d7.d.ts → KState-7c9e40f4.d.ts} +1 -1
  78. package/dist/types/{TwizzleLink-bef52ecd.d.ts → TwizzleLink-3f8a01d2.d.ts} +19 -18
  79. package/dist/types/alg/index.d.ts +30 -8
  80. package/dist/types/bluetooth/index.d.ts +4 -4
  81. package/dist/types/{bluetooth-puzzle-8a678993.d.ts → bluetooth-puzzle-a64e9756.d.ts} +2 -2
  82. package/dist/types/kpuzzle/index.d.ts +2 -2
  83. package/dist/types/notation/index.d.ts +1 -1
  84. package/dist/types/{outside-e55f28a0.d.ts → outside-b62aa614.d.ts} +2 -2
  85. package/dist/types/{parseAlg-a28f7568.d.ts → parseAlg-d5fbee87.d.ts} +1 -1
  86. package/dist/types/protocol/index.d.ts +2 -2
  87. package/dist/types/puzzle-geometry/index.d.ts +3 -3
  88. package/dist/types/puzzles/index.d.ts +8 -6
  89. package/dist/types/scramble/index.d.ts +3 -3
  90. package/dist/types/search/index.d.ts +3 -3
  91. package/dist/types/stream/index.d.ts +3 -3
  92. package/dist/types/twisty/index.d.ts +5 -5
  93. package/package.json +51 -147
  94. package/dist/esm/chunk-AHEXXC6V.js.map +0 -7
  95. package/dist/esm/chunk-NI7U4XAZ.js.map +0 -7
  96. package/dist/esm/chunk-OX6O2ZO5.js.map +0 -7
  97. package/dist/esm/chunk-SBZRVSPK.js +0 -30
  98. package/dist/esm/chunk-SBZRVSPK.js.map +0 -7
  99. package/dist/esm/chunk-U2ONHTIX.js.map +0 -7
  100. package/dist/esm/chunk-XRZBPKES.js.map +0 -7
  101. package/dist/esm/chunk-XT3R2ENM.js.map +0 -7
  102. package/dist/esm/search-dynamic-sgs-side-events-4H3X5HLH.js.map +0 -7
  103. package/dist/esm/search-dynamic-sgs-unofficial-7IRW4LVD.js.map +0 -7
  104. package/dist/esm/search-dynamic-solve-3x3x3-7XZTYQMO.js.map +0 -7
  105. package/dist/esm/search-dynamic-solve-4x4x4-7JTJCCSY.js.map +0 -7
  106. package/dist/esm/search-dynamic-solve-fto-4LI23P6K.js.map +0 -7
  107. package/dist/esm/search-dynamic-solve-kilominx-3HEVQ4MC.js.map +0 -7
  108. package/dist/esm/search-dynamic-solve-master_tetraminx-UB32C7MM.js.map +0 -7
  109. package/dist/esm/search-dynamic-solve-sq1-HA72TYF2.js.map +0 -7
  110. package/dist/esm/search-worker-inside-generated-string-ZEY77HTF.js +0 -3886
  111. package/dist/esm/search-worker-inside-generated-string-ZEY77HTF.js.map +0 -7
  112. package/dist/esm/search-worker-js-entry-T6YIT7YD.js.map +0 -7
  113. package/dist/esm/twisty-dynamic-3d-AZUSXQ5S.js.map +0 -7
@@ -15,22 +15,23 @@ import {
15
15
  TwistyPropSource,
16
16
  customElementsShim,
17
17
  proxy3D,
18
+ rawRenderPooled,
18
19
  setCameraFromOrbitCoordinates,
19
20
  setTwistyDebug
20
- } from "../chunk-XT3R2ENM.js";
21
- import "../chunk-OX6O2ZO5.js";
21
+ } from "../chunk-KOAJIBEX.js";
22
+ import "../chunk-QHWK5RXN.js";
22
23
  import {
23
24
  countAnimatedLeaves,
24
25
  countMoves
25
- } from "../chunk-ZNAYJGVL.js";
26
+ } from "../chunk-C6KMV2PL.js";
26
27
  import {
27
28
  cube3x3x3,
28
29
  puzzles
29
- } from "../chunk-XRZBPKES.js";
30
+ } from "../chunk-35OK6TQ4.js";
30
31
  import {
31
32
  customPGPuzzleLoader
32
- } from "../chunk-U2ONHTIX.js";
33
- import "../chunk-XU5ILFX5.js";
33
+ } from "../chunk-6FB2XWAK.js";
34
+ import "../chunk-GQBRF4EM.js";
34
35
  import {
35
36
  Alg,
36
37
  AlgBuilder,
@@ -43,8 +44,7 @@ import {
43
44
  direct,
44
45
  directedGenerator,
45
46
  experimentalAppendMove
46
- } from "../chunk-NI7U4XAZ.js";
47
- import "../chunk-SBZRVSPK.js";
47
+ } from "../chunk-ZQT3QSWD.js";
48
48
 
49
49
  // src/cubing/twisty/controllers/AnimationTypes.ts
50
50
  function directionScalar(direction) {
@@ -329,7 +329,7 @@ var TwistyPlayerController = class {
329
329
  // src/cubing/twisty/model/props/viewer/ControlPanelProp.ts
330
330
  var controlsLocations = {
331
331
  "bottom-row": true,
332
- "none": true
332
+ none: true
333
333
  };
334
334
  var ControlPanelProp = class extends SimpleTwistyPropSource {
335
335
  getDefaultValue() {
@@ -338,7 +338,8 @@ var ControlPanelProp = class extends SimpleTwistyPropSource {
338
338
  };
339
339
 
340
340
  // src/cubing/twisty/views/TwistyViewerWrapper.css.ts
341
- var twistyViewerWrapperCSS = new CSSSource(`
341
+ var twistyViewerWrapperCSS = new CSSSource(
342
+ `
342
343
  :host {
343
344
  width: 384px;
344
345
  height: 256px;
@@ -376,10 +377,12 @@ var twistyViewerWrapperCSS = new CSSSource(`
376
377
  grid-row: 1 / 2;
377
378
  grid-column: 2 / 3;
378
379
  }
379
- `);
380
+ `
381
+ );
380
382
 
381
383
  // src/cubing/twisty/views/2D/Twisty2DPuzzle.css.ts
382
- var twisty2DSVGCSS = new CSSSource(`
384
+ var twisty2DSVGCSS = new CSSSource(
385
+ `
383
386
  :host {
384
387
  width: 384px;
385
388
  height: 256px;
@@ -410,47 +413,48 @@ svg {
410
413
  from { opacity: 0; }
411
414
  to { opacity: 1; }
412
415
  }
413
- `);
416
+ `
417
+ );
414
418
 
415
419
  // src/cubing/twisty/views/2D/KPuzzleSVGWrapper.ts
416
420
  var xmlns = "http://www.w3.org/2000/svg";
417
421
  var svgCounter = 0;
418
422
  function nextSVGID() {
419
423
  svgCounter += 1;
420
- return "svg" + svgCounter.toString();
424
+ return `svg${svgCounter.toString()}`;
421
425
  }
422
426
  var colorMaps = {
423
427
  dim: {
424
- "white": "#dddddd",
425
- "orange": "#884400",
426
- "limegreen": "#008800",
427
- "red": "#660000",
428
+ white: "#dddddd",
429
+ orange: "#884400",
430
+ limegreen: "#008800",
431
+ red: "#660000",
428
432
  "rgb(34, 102, 255)": "#000088",
429
- "yellow": "#888800"
433
+ yellow: "#888800"
430
434
  },
431
435
  oriented: {
432
- "white": "#44ddcc",
433
- "orange": "#44ddcc",
434
- "limegreen": "#44ddcc",
435
- "red": "#44ddcc",
436
+ white: "#44ddcc",
437
+ orange: "#44ddcc",
438
+ limegreen: "#44ddcc",
439
+ red: "#44ddcc",
436
440
  "rgb(34, 102, 255)": "#44ddcc",
437
- "yellow": "#44ddcc"
441
+ yellow: "#44ddcc"
438
442
  },
439
443
  ignored: {
440
- "white": "#444444",
441
- "orange": "#444444",
442
- "limegreen": "#444444",
443
- "red": "#444444",
444
+ white: "#444444",
445
+ orange: "#444444",
446
+ limegreen: "#444444",
447
+ red: "#444444",
444
448
  "rgb(34, 102, 255)": "#444444",
445
- "yellow": "#444444"
449
+ yellow: "#444444"
446
450
  },
447
451
  invisible: {
448
- "white": "#00000000",
449
- "orange": "#00000000",
450
- "limegreen": "#00000000",
451
- "red": "#00000000",
452
+ white: "#00000000",
453
+ orange: "#00000000",
454
+ limegreen: "#00000000",
455
+ red: "#00000000",
452
456
  "rgb(34, 102, 255)": "#00000000",
453
- "yellow": "#00000000"
457
+ yellow: "#00000000"
454
458
  }
455
459
  };
456
460
  var KPuzzleSVGWrapper = class {
@@ -596,10 +600,10 @@ var KPuzzleSVGWrapper = class {
596
600
  "stop-color",
597
601
  this.originalColors[fromCur]
598
602
  );
599
- this.gradients[id].children[1].setAttribute("offset", `100%`);
600
- this.gradients[id].children[2].setAttribute("offset", `100%`);
601
- this.gradients[id].children[3].setAttribute("offset", `100%`);
602
- this.gradients[id].children[4].setAttribute("offset", `100%`);
603
+ this.gradients[id].children[1].setAttribute("offset", "100%");
604
+ this.gradients[id].children[2].setAttribute("offset", "100%");
605
+ this.gradients[id].children[3].setAttribute("offset", "100%");
606
+ this.gradients[id].children[4].setAttribute("offset", "100%");
603
607
  }
604
608
  }
605
609
  }
@@ -611,7 +615,7 @@ var KPuzzleSVGWrapper = class {
611
615
  "radialGradient"
612
616
  );
613
617
  grad.setAttribute("id", `grad-${this.svgID}-${id}`);
614
- grad.setAttribute("r", `70.7107%`);
618
+ grad.setAttribute("r", "70.7107%");
615
619
  const stopDefs = [
616
620
  { offset: 0, color: originalColor },
617
621
  { offset: 0, color: originalColor },
@@ -630,10 +634,10 @@ var KPuzzleSVGWrapper = class {
630
634
  return grad;
631
635
  }
632
636
  elementID(orbitName, idx, orientation) {
633
- return orbitName + "-l" + idx + "-o" + orientation;
637
+ return `${orbitName}-l${idx}-o${orientation}`;
634
638
  }
635
639
  elementByID(id) {
636
- return this.wrapperElement.querySelector("#" + id);
640
+ return this.wrapperElement.querySelector(`#${id}`);
637
641
  }
638
642
  };
639
643
 
@@ -651,14 +655,11 @@ var Twisty2DPuzzle = class extends ManagedCustomElement {
651
655
  this.#freshListenerManager = new FreshListenerManager();
652
656
  this.addCSS(twisty2DSVGCSS);
653
657
  this.resetSVG();
654
- this.#freshListenerManager.addListener(
655
- this.model.puzzleID,
656
- (puzzleID) => {
657
- if (puzzleLoader?.id !== puzzleID) {
658
- this.disconnect();
659
- }
658
+ this.#freshListenerManager.addListener(this.model.puzzleID, (puzzleID) => {
659
+ if (puzzleLoader?.id !== puzzleID) {
660
+ this.disconnect();
660
661
  }
661
- );
662
+ });
662
663
  this.#freshListenerManager.addListener(
663
664
  this.model.legacyPosition,
664
665
  this.onPositionChange.bind(this)
@@ -741,12 +742,9 @@ var Twisty2DPuzzleWrapper = class {
741
742
  this.puzzleLoader = puzzleLoader;
742
743
  this.effectiveVisualization = effectiveVisualization;
743
744
  this.twisty2DPuzzle();
744
- this.#freshListenerManager.addListener(
745
- this.model.twistySceneModel.stickering,
746
- async (stickering) => {
747
- (await this.twisty2DPuzzle()).experimentalSetStickering(stickering);
748
- }
749
- );
745
+ this.#freshListenerManager.addListener(this.model.twistySceneModel.stickering, async (stickering) => {
746
+ (await this.twisty2DPuzzle()).experimentalSetStickering(stickering);
747
+ });
750
748
  }
751
749
  #freshListenerManager = new FreshListenerManager();
752
750
  disconnect() {
@@ -873,61 +871,46 @@ var Twisty3DPuzzleWrapper = class extends EventTarget {
873
871
  this.puzzleLoader = puzzleLoader;
874
872
  this.visualizationStrategy = visualizationStrategy;
875
873
  this.twisty3DPuzzle();
876
- this.#freshListenerManager.addListener(
877
- this.model.puzzleLoader,
878
- (puzzleLoader2) => {
879
- if (this.puzzleLoader.id !== puzzleLoader2.id) {
880
- this.disconnect();
881
- }
882
- }
883
- );
884
- this.#freshListenerManager.addListener(
885
- this.model.legacyPosition,
886
- async (position) => {
887
- try {
888
- (await this.twisty3DPuzzle()).onPositionChange(position);
889
- this.scheduleRender();
890
- } catch (e) {
891
- this.disconnect();
892
- }
874
+ this.#freshListenerManager.addListener(this.model.puzzleLoader, (puzzleLoader2) => {
875
+ if (this.puzzleLoader.id !== puzzleLoader2.id) {
876
+ this.disconnect();
893
877
  }
894
- );
895
- this.#freshListenerManager.addListener(
896
- this.model.twistySceneModel.hintFacelet,
897
- async (hintFaceletStyle) => {
898
- (await this.twisty3DPuzzle()).experimentalUpdateOptions({
899
- hintFacelets: hintFaceletStyle === "auto" ? "floating" : hintFaceletStyle
900
- });
878
+ });
879
+ this.#freshListenerManager.addListener(this.model.legacyPosition, async (position) => {
880
+ try {
881
+ (await this.twisty3DPuzzle()).onPositionChange(position);
901
882
  this.scheduleRender();
883
+ } catch (e) {
884
+ this.disconnect();
902
885
  }
903
- );
904
- this.#freshListenerManager.addListener(
905
- this.model.twistySceneModel.foundationDisplay,
906
- async (foundationDisplay) => {
907
- (await this.twisty3DPuzzle()).experimentalUpdateOptions({
908
- showFoundation: foundationDisplay !== "none"
909
- });
886
+ });
887
+ this.#freshListenerManager.addListener(this.model.twistySceneModel.hintFacelet, async (hintFaceletStyle) => {
888
+ (await this.twisty3DPuzzle()).experimentalUpdateOptions({
889
+ hintFacelets: hintFaceletStyle === "auto" ? "floating" : hintFaceletStyle
890
+ });
891
+ this.scheduleRender();
892
+ });
893
+ this.#freshListenerManager.addListener(this.model.twistySceneModel.foundationDisplay, async (foundationDisplay) => {
894
+ (await this.twisty3DPuzzle()).experimentalUpdateOptions({
895
+ showFoundation: foundationDisplay !== "none"
896
+ });
897
+ this.scheduleRender();
898
+ });
899
+ this.#freshListenerManager.addListener(this.model.twistySceneModel.stickering, async (stickering) => {
900
+ if ("setStickering" in await this.twisty3DPuzzle()) {
901
+ (await this.twisty3DPuzzle()).setStickering(stickering);
910
902
  this.scheduleRender();
911
- }
912
- );
913
- this.#freshListenerManager.addListener(
914
- this.model.twistySceneModel.stickering,
915
- async (stickering) => {
916
- if ("setStickering" in await this.twisty3DPuzzle()) {
917
- (await this.twisty3DPuzzle()).setStickering(stickering);
903
+ } else {
904
+ if ("appearance" in this.puzzleLoader) {
905
+ const [twisty3D, appearancePromise] = await Promise.all([
906
+ this.twisty3DPuzzle(),
907
+ this.puzzleLoader.appearance(stickering ?? "full")
908
+ ]);
909
+ twisty3D.experimentalSetAppearance(appearancePromise);
918
910
  this.scheduleRender();
919
- } else {
920
- if ("appearance" in this.puzzleLoader) {
921
- const [twisty3D, appearancePromise] = await Promise.all([
922
- this.twisty3DPuzzle(),
923
- this.puzzleLoader.appearance(stickering ?? "full")
924
- ]);
925
- twisty3D.experimentalSetAppearance(appearancePromise);
926
- this.scheduleRender();
927
- }
928
911
  }
929
912
  }
930
- );
913
+ });
931
914
  this.#freshListenerManager.addMultiListener3(
932
915
  [
933
916
  this.model.twistySceneModel.stickering,
@@ -964,14 +947,11 @@ var Twisty3DPuzzleWrapper = class extends EventTarget {
964
947
  this.model.twistySceneModel.hintStickerSprite.get(),
965
948
  this.model.twistySceneModel.stickering.get()
966
949
  ]);
967
- return (await proxyPromise).cube3DShim(
968
- () => this.schedulable.scheduleRender(),
969
- {
970
- foundationSprite,
971
- hintSprite,
972
- experimentalStickering
973
- }
974
- );
950
+ return (await proxyPromise).cube3DShim(() => this.schedulable.scheduleRender(), {
951
+ foundationSprite,
952
+ hintSprite,
953
+ experimentalStickering
954
+ });
975
955
  } else {
976
956
  const [hintFacelets, foundationSprite, hintSprite] = await Promise.all([
977
957
  this.model.twistySceneModel.hintFacelet.get(),
@@ -1001,7 +981,10 @@ var Twisty3DPuzzleWrapper = class extends EventTarget {
1001
981
  return;
1002
982
  }
1003
983
  const targets = puzzle.experimentalGetControlTargets();
1004
- const [raycaster] = await Promise.all([raycasterPromise]);
984
+ const [raycaster, movePressCancelOptions] = await Promise.all([
985
+ raycasterPromise,
986
+ this.model.twistySceneModel.movePressCancelOptions.get()
987
+ ]);
1005
988
  const intersects = raycaster.intersectObjects(targets);
1006
989
  if (intersects.length > 0) {
1007
990
  const closestMove = puzzle.getClosestMoveToAxis(
@@ -1010,8 +993,7 @@ var Twisty3DPuzzleWrapper = class extends EventTarget {
1010
993
  );
1011
994
  if (closestMove) {
1012
995
  this.model.experimentalAddMove(closestMove.move, {
1013
- coalesce: true,
1014
- mod: closestMove.order
996
+ cancel: movePressCancelOptions
1015
997
  });
1016
998
  } else {
1017
999
  console.info("Skipping move!");
@@ -1159,7 +1141,8 @@ var Twisty3DSceneWrapper = class extends ManagedCustomElement {
1159
1141
  customElementsShim.define("twisty-3d-scene-wrapper", Twisty3DSceneWrapper);
1160
1142
 
1161
1143
  // src/cubing/twisty/views/control-panel/TwistyButtons.css.ts
1162
- var buttonGridCSS = new CSSSource(`
1144
+ var buttonGridCSS = new CSSSource(
1145
+ `
1163
1146
  :host {
1164
1147
  width: 384px;
1165
1148
  height: 24px;
@@ -1188,8 +1171,10 @@ var buttonGridCSS = new CSSSource(`
1188
1171
  width: inherit;
1189
1172
  height: inherit;
1190
1173
  }
1191
- `);
1192
- var buttonCSS = new CSSSource(`
1174
+ `
1175
+ );
1176
+ var buttonCSS = new CSSSource(
1177
+ `
1193
1178
  :host:not([hidden]) {
1194
1179
  display: grid;
1195
1180
  }
@@ -1277,7 +1262,8 @@ button.svg-exit-fullscreen {
1277
1262
  button.svg-twizzle-tw {
1278
1263
  background-image: url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iODY0IiBoZWlnaHQ9IjYwMCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBkPSJNMzk3LjU4MSAxNTEuMTh2NTcuMDg0aC04OS43MDN2MjQwLjM1MmgtNjYuOTU1VjIwOC4yNjRIMTUxLjIydi01Ny4wODNoMjQ2LjM2MXptNTQuMzEgNzEuNjc3bDcuNTEyIDMzLjY5MmMyLjcxOCAxMi4xNiA1LjU4IDI0LjY4IDguNTg0IDM3LjU1NWEyMTgwLjc3NSAyMTgwLjc3NSAwIDAwOS40NDIgMzguODQzIDEyNjYuMyAxMjY2LjMgMCAwMDEwLjA4NiAzNy41NTVjMy43Mi0xMi41OSA3LjM2OC0yNS40NjYgMTAuOTQ1LTM4LjYyOCAzLjU3Ni0xMy4xNjIgNy4wMS0yNi4xMSAxMC4zLTM4Ljg0M2w1Ljc2OS0yMi40NTZjMS4yNDgtNC44ODcgMi40NzItOS43MDUgMy42NzQtMTQuNDU1IDMuMDA0LTExLjg3NSA1LjY1MS0yMi45NjIgNy45NC0zMy4yNjNoNDYuMzU0bDIuMzg0IDEwLjU2M2EyMDAwLjc3IDIwMDAuNzcgMCAwMDMuOTM1IDE2LjgyOGw2LjcxMSAyNy43MWMxLjIxMyA0Ljk1NiAyLjQ1IDkuOTggMy43MDkgMTUuMDczYTMxMTkuNzc3IDMxMTkuNzc3IDAgMDA5Ljg3MSAzOC44NDMgMTI0OS4yMjcgMTI0OS4yMjcgMCAwMDEwLjczIDM4LjYyOCAxOTA3LjYwNSAxOTA3LjYwNSAwIDAwMTAuMzAxLTM3LjU1NSAxMzk3Ljk0IDEzOTcuOTQgMCAwMDkuNjU3LTM4Ljg0M2w0LjQtMTkuMDQ2Yy43MTUtMy4xMyAxLjQyMS02LjIzNiAyLjExOC05LjMyMWw5LjU3Ny00Mi44OGg2Ni41MjZhMjk4OC43MTggMjk4OC43MTggMCAwMS0xOS41MjkgNjYuMzExbC01LjcyOCAxOC40ODJhMzIzNy40NiAzMjM3LjQ2IDAgMDEtMTQuMDE1IDQzLjc1MmMtNi40MzggMTkuNi0xMi43MzMgMzcuNjk4LTE4Ljg4NSA1NC4yOTRsLTMuMzA2IDguODI1Yy00Ljg4NCAxMi44OTgtOS40MzMgMjQuMjYzLTEzLjY0NyAzNC4wOTVoLTQ5Ljc4N2E4NDE3LjI4OSA4NDE3LjI4OSAwIDAxLTIxLjAzMS02NC44MDkgMTI4OC42ODYgMTI4OC42ODYgMCAwMS0xOC44ODUtNjQuODEgMTk3Mi40NDQgMTk3Mi40NDQgMCAwMS0xOC4yNCA2NC44MSAyNTc5LjQxMiAyNTc5LjQxMiAwIDAxLTIwLjM4OCA2NC44MWgtNDkuNzg3Yy00LjY4Mi0xMC45MjYtOS43Mi0yMy43NDMtMTUuMTEtMzguNDUxbC0xLjYyOS00LjQ3Yy01LjI1OC0xNC41MjEtMTAuNjgtMzAuMTkyLTE2LjI2Ni00Ny4wMTRsLTIuNDA0LTcuMjhjLTYuNDM4LTE5LjYtMTMuMDItNDAuMzQ0LTE5Ljc0My02Mi4yMzRhMjk4OC43MDcgMjk4OC43MDcgMCAwMS0xOS41MjktNjYuMzExaDY3LjM4NXoiIGZpbGw9IiM0Mjg1RjQiIGZpbGwtcnVsZT0ibm9uemVybyIvPjwvc3ZnPg==");
1279
1264
  }
1280
- `);
1265
+ `
1266
+ );
1281
1267
 
1282
1268
  // src/cubing/twisty/views/document.ts
1283
1269
  var globalSafeDocument = typeof document === "undefined" ? null : document;
@@ -1321,7 +1307,7 @@ var buttonIcons = [
1321
1307
  var ButtonAppearanceProp = class extends TwistyPropDerived {
1322
1308
  derive(inputs) {
1323
1309
  const buttonAppearances = {
1324
- "fullscreen": {
1310
+ fullscreen: {
1325
1311
  enabled: fullscreenEnabled,
1326
1312
  icon: document.fullscreenElement === null ? "enter-fullscreen" : "exit-fullscreen",
1327
1313
  title: "Enter fullscreen"
@@ -1364,7 +1350,7 @@ var ButtonAppearanceProp = class extends TwistyPropDerived {
1364
1350
 
1365
1351
  // src/cubing/twisty/views/control-panel/TwistyButtons.ts
1366
1352
  var buttonCommands = {
1367
- "fullscreen": true,
1353
+ fullscreen: true,
1368
1354
  "jump-to-start": true,
1369
1355
  "play-step-backwards": true,
1370
1356
  "play-pause": true,
@@ -1397,33 +1383,40 @@ var TwistyButtons = class extends ManagedCustomElement {
1397
1383
  }
1398
1384
  #onCommand(command) {
1399
1385
  switch (command) {
1400
- case "fullscreen":
1386
+ case "fullscreen": {
1401
1387
  this.onFullscreenButton();
1402
1388
  break;
1403
- case "jump-to-start":
1389
+ }
1390
+ case "jump-to-start": {
1404
1391
  this.controller?.jumpToStart({ flash: true });
1405
1392
  break;
1406
- case "play-step-backwards":
1393
+ }
1394
+ case "play-step-backwards": {
1407
1395
  this.controller?.animationController.play({
1408
1396
  direction: -1 /* Backwards */,
1409
1397
  untilBoundary: "move" /* Move */
1410
1398
  });
1411
1399
  break;
1412
- case "play-pause":
1400
+ }
1401
+ case "play-pause": {
1413
1402
  this.controller?.togglePlay();
1414
1403
  break;
1415
- case "play-step":
1404
+ }
1405
+ case "play-step": {
1416
1406
  this.controller?.animationController.play({
1417
1407
  direction: 1 /* Forwards */,
1418
1408
  untilBoundary: "move" /* Move */
1419
1409
  });
1420
1410
  break;
1421
- case "jump-to-end":
1411
+ }
1412
+ case "jump-to-end": {
1422
1413
  this.controller?.jumpToEnd({ flash: true });
1423
1414
  break;
1424
- case "twizzle-link":
1415
+ }
1416
+ case "twizzle-link": {
1425
1417
  this.controller?.visitTwizzleLink();
1426
1418
  break;
1419
+ }
1427
1420
  default:
1428
1421
  throw new Error("Missing command");
1429
1422
  }
@@ -1480,7 +1473,8 @@ var TwistyButton = class extends ManagedCustomElement {
1480
1473
  customElementsShim.define("twisty-button", TwistyButton);
1481
1474
 
1482
1475
  // src/cubing/twisty/views/control-panel/TwistyScrubber.css.ts
1483
- var twistyScrubberCSS = new CSSSource(`
1476
+ var twistyScrubberCSS = new CSSSource(
1477
+ `
1484
1478
  :host {
1485
1479
  width: 384px;
1486
1480
  height: 16px;
@@ -1500,7 +1494,8 @@ var twistyScrubberCSS = new CSSSource(`
1500
1494
  input:not(:disabled) {
1501
1495
  cursor: ew-resize;
1502
1496
  }
1503
- `);
1497
+ `
1498
+ );
1504
1499
 
1505
1500
  // src/cubing/twisty/views/control-panel/TwistyScrubber.ts
1506
1501
  var SLOW_DOWN_SCRUBBING = false;
@@ -1542,9 +1537,10 @@ var lastPreval = 0;
1542
1537
  var scaling = false;
1543
1538
  var currentClickNum = 0;
1544
1539
  var TwistyScrubber = class extends ManagedCustomElement {
1545
- constructor(model) {
1540
+ constructor(model, controller) {
1546
1541
  super();
1547
1542
  this.model = model;
1543
+ this.controller = controller;
1548
1544
  }
1549
1545
  async onDetailedTimelineInfo(detailedTimelineInfo) {
1550
1546
  const inputElem = await this.inputElem();
@@ -1567,6 +1563,7 @@ var TwistyScrubber = class extends ManagedCustomElement {
1567
1563
  this.onDetailedTimelineInfo.bind(this)
1568
1564
  );
1569
1565
  elem.addEventListener("input", this.onInput.bind(this));
1566
+ elem.addEventListener("keydown", this.onKeypress.bind(this));
1570
1567
  return elem;
1571
1568
  })());
1572
1569
  }
@@ -1580,6 +1577,24 @@ var TwistyScrubber = class extends ManagedCustomElement {
1580
1577
  this.model?.playingInfo.set({ playing: false });
1581
1578
  this.model?.timestampRequest.set(value);
1582
1579
  }
1580
+ onKeypress(e) {
1581
+ switch (e.key) {
1582
+ case "ArrowLeft":
1583
+ case "ArrowRight": {
1584
+ this.controller?.animationController.play({
1585
+ direction: e.key === "ArrowLeft" ? -1 /* Backwards */ : 1 /* Forwards */,
1586
+ untilBoundary: "move" /* Move */
1587
+ });
1588
+ e.preventDefault();
1589
+ break;
1590
+ }
1591
+ case " ": {
1592
+ this.controller?.togglePlay();
1593
+ e.preventDefault();
1594
+ break;
1595
+ }
1596
+ }
1597
+ }
1583
1598
  async slowDown(e, inputElem) {
1584
1599
  if (!SLOW_DOWN_SCRUBBING) {
1585
1600
  return;
@@ -1617,33 +1632,39 @@ customElementsShim.define("twisty-scrubber", TwistyScrubber);
1617
1632
  // src/cubing/twisty/views/screenshot.ts
1618
1633
  var cachedCamera = null;
1619
1634
  async function screenshot(model, options) {
1635
+ const [
1636
+ { PerspectiveCamera, Scene },
1637
+ puzzleLoader,
1638
+ visualizationStrategy,
1639
+ _stickering,
1640
+ _legacyPosition,
1641
+ orbitCoordinates
1642
+ ] = await Promise.all([
1643
+ THREEJS,
1644
+ await model.puzzleLoader.get(),
1645
+ await model.visualizationStrategy.get(),
1646
+ await model.twistySceneModel.stickering.get(),
1647
+ await model.legacyPosition.get(),
1648
+ await model.twistySceneModel.orbitCoordinates.get()
1649
+ ]);
1620
1650
  const width = options?.width ?? 2048;
1621
1651
  const height = options?.height ?? 2048;
1622
1652
  const aspectRatio = width / height;
1623
1653
  const camera = cachedCamera ?? (cachedCamera = await (async () => {
1624
- return new (await THREEJS).PerspectiveCamera(20, aspectRatio, 0.1, 20);
1654
+ return new PerspectiveCamera(20, aspectRatio, 0.1, 20);
1625
1655
  })());
1626
- const scene = new (await THREEJS).Scene();
1656
+ const scene = new Scene();
1627
1657
  const twisty3DWrapper = new Twisty3DPuzzleWrapper(
1628
1658
  model,
1629
1659
  { scheduleRender: () => {
1630
1660
  } },
1631
- await model.puzzleLoader.get(),
1632
- await model.visualizationStrategy.get()
1661
+ puzzleLoader,
1662
+ visualizationStrategy
1633
1663
  );
1634
- await model.twistySceneModel.stickering.get();
1635
- await new Promise((resolve) => setTimeout(resolve, 1e3));
1636
- await model.legacyPosition.get();
1637
1664
  scene.add(await twisty3DWrapper.twisty3DPuzzle());
1638
- const orbitCoordinates = await model.twistySceneModel.orbitCoordinates.get();
1639
1665
  await setCameraFromOrbitCoordinates(camera, orbitCoordinates);
1640
- const renderer = new (await THREEJS).WebGLRenderer({
1641
- antialias: true,
1642
- alpha: true
1643
- });
1644
- renderer.setSize(width, height);
1645
- renderer.render(scene, camera);
1646
- const dataURL = renderer.domElement.toDataURL();
1666
+ const rendererCanvas = await rawRenderPooled(width, height, scene, camera);
1667
+ const dataURL = rendererCanvas.toDataURL();
1647
1668
  const defaultFilename = await getDefaultFilename(model);
1648
1669
  return {
1649
1670
  dataURL,
@@ -1657,7 +1678,7 @@ async function getDefaultFilename(model) {
1657
1678
  model.puzzleID.get(),
1658
1679
  model.alg.get()
1659
1680
  ]);
1660
- return `[${puzzleID}]${algWithIssues.alg.experimentalNumChildAlgNodes() === 0 ? "" : " " + algWithIssues.alg.toString()}`;
1681
+ return `[${puzzleID}]${algWithIssues.alg.experimentalNumChildAlgNodes() === 0 ? "" : ` ${algWithIssues.alg.toString()}`}`;
1661
1682
  }
1662
1683
  function downloadURL(url, name, extension = "png") {
1663
1684
  const a = document.createElement("a");
@@ -1667,7 +1688,8 @@ function downloadURL(url, name, extension = "png") {
1667
1688
  }
1668
1689
 
1669
1690
  // src/cubing/twisty/views/TwistyPlayer.css.ts
1670
- var twistyPlayerCSS = new CSSSource(`
1691
+ var twistyPlayerCSS = new CSSSource(
1692
+ `
1671
1693
  :host {
1672
1694
  width: 384px;
1673
1695
  height: 256px;
@@ -1736,7 +1758,8 @@ twisty-scrubber {
1736
1758
  .wrapper.error .error-elem {
1737
1759
  display: grid;
1738
1760
  }
1739
- `);
1761
+ `
1762
+ );
1740
1763
 
1741
1764
  // src/cubing/twisty/model/props/general/ArbitraryStringProp.ts
1742
1765
  var ArbitraryStringProp = class extends SimpleTwistyPropSource {
@@ -1786,7 +1809,7 @@ function algWithIssuesFromString(s) {
1786
1809
  const alg = Alg.fromString(s);
1787
1810
  const warnings = [];
1788
1811
  if (alg.toString() !== s) {
1789
- warnings.push(`Alg is non-canonical!`);
1812
+ warnings.push("Alg is non-canonical!");
1790
1813
  }
1791
1814
  return {
1792
1815
  alg,
@@ -2052,7 +2075,9 @@ var SimpleAlgIndexer = class {
2052
2075
  return i;
2053
2076
  }
2054
2077
  stateAtIndex(index) {
2055
- return this.kpuzzle.startState().applyTransformation(this.transformationAtIndex(index));
2078
+ return this.kpuzzle.startState().applyTransformation(
2079
+ this.transformationAtIndex(index)
2080
+ );
2056
2081
  }
2057
2082
  transformationAtIndex(index) {
2058
2083
  let state = this.kpuzzle.identityTransformation();
@@ -2347,16 +2372,18 @@ var SimultaneousMoveIndexer = class {
2347
2372
  endTimestamp: leafWithRange.end
2348
2373
  };
2349
2374
  switch (fraction) {
2350
- case 0:
2375
+ case 0: {
2351
2376
  movesStarting.push(currentMove);
2352
2377
  break;
2353
- case 1:
2378
+ }
2379
+ case 1: {
2354
2380
  if (moveFinished) {
2355
2381
  movesFinished.push(currentMove);
2356
2382
  } else {
2357
2383
  movesFinishing.push(currentMove);
2358
2384
  }
2359
2385
  break;
2386
+ }
2360
2387
  default:
2361
2388
  currentMoves.push(currentMove);
2362
2389
  latestStart = Math.max(latestStart, leafWithRange.start);
@@ -2489,13 +2516,7 @@ var DecoratorConstructor = class extends TraversalUp {
2489
2516
  const AB = decA.forward.applyTransformation(decB.forward);
2490
2517
  const ApBp = decA.backward.applyTransformation(decB.backward);
2491
2518
  const ABApBp = AB.applyTransformation(ApBp);
2492
- const dec = new AlgWalkterDecoration(
2493
- 2 * (decA.moveCount + decB.moveCount),
2494
- 2 * (decA.duration + decB.duration),
2495
- ABApBp,
2496
- ABApBp.invert(),
2497
- [decA, decB]
2498
- );
2519
+ const dec = new AlgWalkterDecoration(2 * (decA.moveCount + decB.moveCount), 2 * (decA.duration + decB.duration), ABApBp, ABApBp.invert(), [decA, decB]);
2499
2520
  return this.mult(dec, 1, [dec, decA, decB]);
2500
2521
  }
2501
2522
  traverseConjugate(conjugate) {
@@ -2503,13 +2524,10 @@ var DecoratorConstructor = class extends TraversalUp {
2503
2524
  const decB = this.traverseAlg(conjugate.B);
2504
2525
  const AB = decA.forward.applyTransformation(decB.forward);
2505
2526
  const ABAp = AB.applyTransformation(decA.backward);
2506
- const dec = new AlgWalkterDecoration(
2507
- 2 * decA.moveCount + decB.moveCount,
2508
- 2 * decA.duration + decB.duration,
2509
- ABAp,
2510
- ABAp.invert(),
2511
- [decA, decB]
2512
- );
2527
+ const dec = new AlgWalkterDecoration(2 * decA.moveCount + decB.moveCount, 2 * decA.duration + decB.duration, ABAp, ABAp.invert(), [
2528
+ decA,
2529
+ decB
2530
+ ]);
2513
2531
  return this.mult(dec, 1, [dec, decA, decB]);
2514
2532
  }
2515
2533
  traversePause(pause) {
@@ -3085,9 +3103,9 @@ var TempoScaleProp = class extends TwistyPropSource {
3085
3103
 
3086
3104
  // src/cubing/twisty/model/props/timeline/TimestampRequestProp.ts
3087
3105
  var smartTimestamps = {
3088
- "start": true,
3089
- "end": true,
3090
- "anchor": true,
3106
+ start: true,
3107
+ end: true,
3108
+ anchor: true,
3091
3109
  "opposite-anchor": true
3092
3110
  };
3093
3111
  var TimestampRequestProp = class extends SimpleTwistyPropSource {
@@ -3113,7 +3131,7 @@ var TimestampRequestProp = class extends SimpleTwistyPropSource {
3113
3131
 
3114
3132
  // src/cubing/twisty/model/props/viewer/BackViewProp.ts
3115
3133
  var backViewLayouts = {
3116
- "none": true,
3134
+ none: true,
3117
3135
  "side-by-side": true,
3118
3136
  "top-right": true
3119
3137
  };
@@ -3233,6 +3251,13 @@ var DragInputProp = class extends SimpleTwistyPropSource {
3233
3251
  }
3234
3252
  };
3235
3253
 
3254
+ // src/cubing/twisty/model/props/puzzle/state/MovePressCancelOptions.ts
3255
+ var MovePressCancelOptions = class extends SimpleTwistyPropSource {
3256
+ getDefaultValue() {
3257
+ return {};
3258
+ }
3259
+ };
3260
+
3236
3261
  // src/cubing/twisty/model/props/puzzle/state/MovePressInputProp.ts
3237
3262
  var MovePressInputProp = class extends SimpleTwistyPropSource {
3238
3263
  getDefaultValue() {
@@ -3374,6 +3399,7 @@ var TwistySceneModel = class {
3374
3399
  this.hintStickerSpriteURL = new URLProp();
3375
3400
  this.latitudeLimit = new LatitudeLimitProp();
3376
3401
  this.movePressInput = new MovePressInputProp();
3402
+ this.movePressCancelOptions = new MovePressCancelOptions();
3377
3403
  this.orbitCoordinatesRequest = new OrbitCoordinatesRequestProp();
3378
3404
  this.stickering = new StickeringProp();
3379
3405
  this.foundationStickerSprite = new SpriteProp({
@@ -3548,7 +3574,7 @@ var TwistyPlayerModel = class {
3548
3574
  }
3549
3575
  return url.toString();
3550
3576
  }
3551
- experimentalAddAlgLeaf(algLeaf, options = {}) {
3577
+ experimentalAddAlgLeaf(algLeaf, options) {
3552
3578
  const maybeMove = algLeaf.as(Move);
3553
3579
  if (maybeMove) {
3554
3580
  this.experimentalAddMove(maybeMove, options);
@@ -3563,14 +3589,17 @@ var TwistyPlayerModel = class {
3563
3589
  );
3564
3590
  }
3565
3591
  }
3566
- experimentalAddMove(flexibleMove, options = {}) {
3592
+ experimentalAddMove(flexibleMove, options) {
3567
3593
  const move = typeof flexibleMove === "string" ? new Move(flexibleMove) : flexibleMove;
3568
3594
  this.alg.set(
3569
3595
  (async () => {
3570
- const alg = (await this.alg.get()).alg;
3596
+ const [{ alg }, puzzleLoader] = await Promise.all([
3597
+ this.alg.get(),
3598
+ this.puzzleLoader.get()
3599
+ ]);
3571
3600
  const newAlg = experimentalAppendMove(alg, move, {
3572
- coalesce: options?.coalesce,
3573
- mod: options?.mod
3601
+ ...options,
3602
+ puzzleLoader
3574
3603
  });
3575
3604
  this.timestampRequest.set("end");
3576
3605
  this.catchUpMove.set({
@@ -3581,6 +3610,27 @@ var TwistyPlayerModel = class {
3581
3610
  })()
3582
3611
  );
3583
3612
  }
3613
+ experimentalRemoveFinalChild() {
3614
+ this.alg.set(
3615
+ (async () => {
3616
+ const alg = (await this.alg.get()).alg;
3617
+ const children = Array.from(alg.childAlgNodes());
3618
+ const [finalChild] = children.splice(-1);
3619
+ if (!finalChild) {
3620
+ return alg;
3621
+ }
3622
+ this.timestampRequest.set("end");
3623
+ const finalChildMove = finalChild.as(Move);
3624
+ if (finalChildMove) {
3625
+ this.catchUpMove.set({
3626
+ move: finalChildMove.invert(),
3627
+ amount: 0
3628
+ });
3629
+ }
3630
+ return new Alg(children);
3631
+ })()
3632
+ );
3633
+ }
3584
3634
  };
3585
3635
 
3586
3636
  // src/cubing/twisty/views/TwistyPlayerSettable.ts
@@ -3697,20 +3747,34 @@ var TwistyPlayerSettable = class extends ManagedCustomElement {
3697
3747
  get experimentalMovePressInput() {
3698
3748
  throw err("experimentalMovePressInput");
3699
3749
  }
3750
+ set experimentalMovePressCancelOptions(movePressCancelOptions) {
3751
+ this.experimentalModel.twistySceneModel.movePressCancelOptions.set(
3752
+ movePressCancelOptions
3753
+ );
3754
+ }
3755
+ get experimentalMovePressCancelOptions() {
3756
+ throw err("experimentalMovePressCancelOptions");
3757
+ }
3700
3758
  set cameraLatitude(latitude) {
3701
- this.experimentalModel.twistySceneModel.orbitCoordinatesRequest.set({ latitude });
3759
+ this.experimentalModel.twistySceneModel.orbitCoordinatesRequest.set({
3760
+ latitude
3761
+ });
3702
3762
  }
3703
3763
  get cameraLatitude() {
3704
3764
  throw err("cameraLatitude");
3705
3765
  }
3706
3766
  set cameraLongitude(longitude) {
3707
- this.experimentalModel.twistySceneModel.orbitCoordinatesRequest.set({ longitude });
3767
+ this.experimentalModel.twistySceneModel.orbitCoordinatesRequest.set({
3768
+ longitude
3769
+ });
3708
3770
  }
3709
3771
  get cameraLongitude() {
3710
3772
  throw err("cameraLongitude");
3711
3773
  }
3712
3774
  set cameraDistance(distance) {
3713
- this.experimentalModel.twistySceneModel.orbitCoordinatesRequest.set({ distance });
3775
+ this.experimentalModel.twistySceneModel.orbitCoordinatesRequest.set({
3776
+ distance
3777
+ });
3714
3778
  }
3715
3779
  get cameraDistance() {
3716
3780
  throw err("cameraDistance");
@@ -3773,15 +3837,15 @@ var ExperimentalGetters = class {
3773
3837
  // src/cubing/twisty/views/TwistyPlayer.ts
3774
3838
  var DATA_ATTRIBUTE_PREFIX = "data-";
3775
3839
  var twistyPlayerAttributeMap = {
3776
- "alg": "alg",
3840
+ alg: "alg",
3777
3841
  "experimental-setup-alg": "experimentalSetupAlg",
3778
3842
  "experimental-setup-anchor": "experimentalSetupAnchor",
3779
- "puzzle": "puzzle",
3843
+ puzzle: "puzzle",
3780
3844
  "experimental-puzzle-description": "experimentalPuzzleDescription",
3781
- "visualization": "visualization",
3845
+ visualization: "visualization",
3782
3846
  "hint-facelets": "hintFacelets",
3783
3847
  "experimental-stickering": "experimentalStickering",
3784
- "background": "background",
3848
+ background: "background",
3785
3849
  "control-panel": "controlPanel",
3786
3850
  "back-view": "backView",
3787
3851
  "viewer-link": "viewerLink",
@@ -3801,6 +3865,9 @@ var twistyPlayerAttributeMap = {
3801
3865
  var configKeys = Object.fromEntries(
3802
3866
  Object.values(twistyPlayerAttributeMap).map((s) => [s, true])
3803
3867
  );
3868
+ var propOnly = {
3869
+ experimentalMovePressCancelOptions: true
3870
+ };
3804
3871
  var TwistyPlayer = class extends TwistyPlayerSettable {
3805
3872
  constructor(config = {}) {
3806
3873
  super();
@@ -3825,7 +3892,7 @@ var TwistyPlayer = class extends TwistyPlayerSettable {
3825
3892
  this.#initial3DVisualizationWrapper = new InitialValueTracker();
3826
3893
  this.#visualizationStrategy = null;
3827
3894
  for (const [propName, value] of Object.entries(config)) {
3828
- if (!configKeys[propName]) {
3895
+ if (!(configKeys[propName] || propOnly[propName])) {
3829
3896
  console.warn(`Invalid config passed to TwistyPlayer: ${propName}`);
3830
3897
  break;
3831
3898
  }
@@ -3847,16 +3914,17 @@ var TwistyPlayer = class extends TwistyPlayerSettable {
3847
3914
  );
3848
3915
  this.addElement(this.#errorElem).classList.add("error-elem");
3849
3916
  this.#errorElem.textContent = "Error";
3850
- this.experimentalModel.userVisibleErrorTracker.addFreshListener(
3851
- (userVisibleError) => {
3852
- const errorString = userVisibleError.errors[0] ?? null;
3853
- this.contentWrapper.classList.toggle("error", !!errorString);
3854
- if (errorString) {
3855
- this.#errorElem.textContent = errorString;
3856
- }
3917
+ this.experimentalModel.userVisibleErrorTracker.addFreshListener((userVisibleError) => {
3918
+ const errorString = userVisibleError.errors[0] ?? null;
3919
+ this.contentWrapper.classList.toggle("error", !!errorString);
3920
+ if (errorString) {
3921
+ this.#errorElem.textContent = errorString;
3857
3922
  }
3923
+ });
3924
+ const scrubber = new TwistyScrubber(
3925
+ this.experimentalModel,
3926
+ this.controller
3858
3927
  );
3859
- const scrubber = new TwistyScrubber(this.experimentalModel);
3860
3928
  this.contentWrapper.appendChild(scrubber);
3861
3929
  this.buttons = new TwistyButtons(
3862
3930
  this.experimentalModel,
@@ -3864,19 +3932,15 @@ var TwistyPlayer = class extends TwistyPlayerSettable {
3864
3932
  this
3865
3933
  );
3866
3934
  this.contentWrapper.appendChild(this.buttons);
3867
- this.experimentalModel.twistySceneModel.background.addFreshListener(
3868
- (backgroundTheme) => {
3869
- this.contentWrapper.classList.toggle(
3870
- "checkered",
3871
- backgroundTheme !== "none"
3872
- );
3873
- }
3874
- );
3875
- this.experimentalModel.controlPanel.addFreshListener(
3876
- (controlPanel) => {
3877
- this.#controlsManager.setValue(controlPanel);
3878
- }
3879
- );
3935
+ this.experimentalModel.twistySceneModel.background.addFreshListener((backgroundTheme) => {
3936
+ this.contentWrapper.classList.toggle(
3937
+ "checkered",
3938
+ backgroundTheme !== "none"
3939
+ );
3940
+ });
3941
+ this.experimentalModel.controlPanel.addFreshListener((controlPanel) => {
3942
+ this.#controlsManager.setValue(controlPanel);
3943
+ });
3880
3944
  this.experimentalModel.visualizationStrategy.addFreshListener(
3881
3945
  this.#setVisualizationWrapper.bind(this)
3882
3946
  );
@@ -3904,17 +3968,19 @@ var TwistyPlayer = class extends TwistyPlayerSettable {
3904
3968
  let newWrapper;
3905
3969
  switch (strategy) {
3906
3970
  case "2D":
3907
- case "experimental-2D-LL":
3971
+ case "experimental-2D-LL": {
3908
3972
  newWrapper = new Twisty2DSceneWrapper(
3909
3973
  this.experimentalModel.twistySceneModel,
3910
3974
  strategy
3911
3975
  );
3912
3976
  break;
3977
+ }
3913
3978
  case "Cube3D":
3914
- case "PG3D":
3979
+ case "PG3D": {
3915
3980
  newWrapper = new Twisty3DSceneWrapper(this.experimentalModel);
3916
3981
  this.#initial3DVisualizationWrapper.handleNewValue(newWrapper);
3917
3982
  break;
3983
+ }
3918
3984
  default:
3919
3985
  throw new Error("Invalid visualization");
3920
3986
  }
@@ -3976,10 +4042,10 @@ var TwistyPlayer = class extends TwistyPlayerSettable {
3976
4042
  togglePlay(play) {
3977
4043
  this.controller.togglePlay(play);
3978
4044
  }
3979
- experimentalAddMove(flexibleMove, options = {}) {
4045
+ experimentalAddMove(flexibleMove, options) {
3980
4046
  this.experimentalModel.experimentalAddMove(flexibleMove, options);
3981
4047
  }
3982
- experimentalAddAlgLeaf(algLeaf, options = {}) {
4048
+ experimentalAddAlgLeaf(algLeaf, options) {
3983
4049
  this.experimentalModel.experimentalAddAlgLeaf(algLeaf, options);
3984
4050
  }
3985
4051
  static get observedAttributes() {
@@ -3989,6 +4055,9 @@ var TwistyPlayer = class extends TwistyPlayerSettable {
3989
4055
  }
3990
4056
  return observed;
3991
4057
  }
4058
+ experimentalRemoveFinalChild() {
4059
+ this.experimentalModel.experimentalRemoveFinalChild();
4060
+ }
3992
4061
  attributeChangedCallback(attributeName, _oldValue, newValue) {
3993
4062
  if (attributeName.startsWith(DATA_ATTRIBUTE_PREFIX)) {
3994
4063
  attributeName = attributeName.slice(DATA_ATTRIBUTE_PREFIX.length);
@@ -4025,7 +4094,8 @@ var TwistyPlayer = class extends TwistyPlayerSettable {
4025
4094
  customElementsShim.define("twisty-player", TwistyPlayer);
4026
4095
 
4027
4096
  // src/cubing/twisty/views/TwistyAlgViewer.css.ts
4028
- var twistyAlgViewerCSS = new CSSSource(`
4097
+ var twistyAlgViewerCSS = new CSSSource(
4098
+ `
4029
4099
  :host {
4030
4100
  display: inline;
4031
4101
  }
@@ -4051,7 +4121,8 @@ twisty-alg-leaf-elem.twisty-alg-comment {
4051
4121
  padding-right: 0.1em;
4052
4122
  border-radius: 0.1em;
4053
4123
  }
4054
- `);
4124
+ `
4125
+ );
4055
4126
 
4056
4127
  // src/cubing/twisty/views/TwistyAlgViewer.ts
4057
4128
  var DEFAULT_OFFSET_MS = 250;
@@ -4204,7 +4275,7 @@ var AlgToDOMTree = class extends TraversalDownUp {
4204
4275
  })
4205
4276
  );
4206
4277
  }
4207
- element.addString(")" + grouping.experimentalRepetitionSuffix);
4278
+ element.addString(`)${grouping.experimentalRepetitionSuffix}`);
4208
4279
  element.flushQueue();
4209
4280
  return {
4210
4281
  moveCount: moveCount * Math.abs(grouping.amount),
@@ -4391,34 +4462,28 @@ var TwistyAlgViewer = class extends HTMLElementShim {
4391
4462
  throw new Error("clearing twistyPlayer is not supported");
4392
4463
  }
4393
4464
  this.#twistyPlayer = twistyPlayer;
4394
- this.#twistyPlayer.experimentalModel.alg.addFreshListener(
4395
- (algWithIssues) => {
4396
- this.setAlg(algWithIssues.alg);
4397
- }
4398
- );
4465
+ this.#twistyPlayer.experimentalModel.alg.addFreshListener((algWithIssues) => {
4466
+ this.setAlg(algWithIssues.alg);
4467
+ });
4399
4468
  const sourceAlg = (await this.#twistyPlayer.experimentalModel.alg.get()).alg;
4400
4469
  const parsedAlg = "startCharIndex" in sourceAlg ? sourceAlg : Alg.fromString(sourceAlg.toString());
4401
4470
  this.setAlg(parsedAlg);
4402
- twistyPlayer.experimentalModel.currentMoveInfo.addFreshListener(
4403
- (currentMoveInfo) => {
4404
- let moveInfo = currentMoveInfo.currentMoves[0];
4405
- moveInfo ?? (moveInfo = currentMoveInfo.movesStarting[0]);
4406
- moveInfo ?? (moveInfo = currentMoveInfo.movesFinishing[0]);
4407
- if (!moveInfo) {
4408
- this.highlighter.set(null);
4409
- } else {
4410
- const mainCurrentMove = moveInfo.move;
4411
- this.highlighter.set(mainCurrentMove);
4412
- }
4471
+ twistyPlayer.experimentalModel.currentMoveInfo.addFreshListener((currentMoveInfo) => {
4472
+ let moveInfo = currentMoveInfo.currentMoves[0];
4473
+ moveInfo ?? (moveInfo = currentMoveInfo.movesStarting[0]);
4474
+ moveInfo ?? (moveInfo = currentMoveInfo.movesFinishing[0]);
4475
+ if (!moveInfo) {
4476
+ this.highlighter.set(null);
4477
+ } else {
4478
+ const mainCurrentMove = moveInfo.move;
4479
+ this.highlighter.set(mainCurrentMove);
4413
4480
  }
4414
- );
4415
- twistyPlayer.experimentalModel.detailedTimelineInfo.addFreshListener(
4416
- (detailedTimelineInfo) => {
4417
- if (detailedTimelineInfo.timestamp !== this.lastClickTimestamp) {
4418
- this.lastClickTimestamp = null;
4419
- }
4481
+ });
4482
+ twistyPlayer.experimentalModel.detailedTimelineInfo.addFreshListener((detailedTimelineInfo) => {
4483
+ if (detailedTimelineInfo.timestamp !== this.lastClickTimestamp) {
4484
+ this.lastClickTimestamp = null;
4420
4485
  }
4421
- );
4486
+ });
4422
4487
  }
4423
4488
  async jumpToIndex(index, offsetIntoMove) {
4424
4489
  const twistyPlayer = this.#twistyPlayer;
@@ -4632,7 +4697,8 @@ var TwistyAlgEditorModel = class {
4632
4697
  };
4633
4698
 
4634
4699
  // src/cubing/twisty/views/TwistyAlgEditor/TwistyAlgEditor.css.ts
4635
- var twistyAlgEditorCSS = new CSSSource(`
4700
+ var twistyAlgEditorCSS = new CSSSource(
4701
+ `
4636
4702
  :host {
4637
4703
  width: 384px;
4638
4704
  display: grid;
@@ -4701,7 +4767,8 @@ textarea {
4701
4767
  border: 1px solid red;
4702
4768
  background: rgba(255, 0, 0, 0.1);
4703
4769
  }
4704
- `);
4770
+ `
4771
+ );
4705
4772
 
4706
4773
  // src/cubing/twisty/views/TwistyAlgEditor/TwistyAlgEditor.ts
4707
4774
  var ATTRIBUTE_FOR_TWISTY_PLAYER = "for-twisty-player";
@@ -4752,13 +4819,11 @@ var TwistyAlgEditor = class extends ManagedCustomElement {
4752
4819
  }
4753
4820
  this.#twistyPlayerProp = options?.twistyPlayerProp ?? "alg";
4754
4821
  if (options?.twistyPlayerProp === "alg") {
4755
- this.model.leafToHighlight.addFreshListener(
4756
- (highlightInfo) => {
4757
- if (highlightInfo) {
4758
- this.highlightLeaf(highlightInfo.leafInfo.leaf);
4759
- }
4822
+ this.model.leafToHighlight.addFreshListener((highlightInfo) => {
4823
+ if (highlightInfo) {
4824
+ this.highlightLeaf(highlightInfo.leafInfo.leaf);
4760
4825
  }
4761
- );
4826
+ });
4762
4827
  }
4763
4828
  }
4764
4829
  #textarea;
@@ -4813,7 +4878,7 @@ var TwistyAlgEditor = class extends ManagedCustomElement {
4813
4878
  this.#textareaClassListValidForPuzzleManager.setValue(issues);
4814
4879
  }
4815
4880
  #padSuffix(s) {
4816
- return s.endsWith("\n") ? s + " " : s;
4881
+ return s.endsWith("\n") ? `${s} ` : s;
4817
4882
  }
4818
4883
  #highlightedLeaf;
4819
4884
  highlightLeaf(leaf) {
@@ -4861,62 +4926,61 @@ var TwistyAlgEditor = class extends ManagedCustomElement {
4861
4926
  this.algString = this.#algProp ? (await this.#algProp.get()).alg.toString() : "";
4862
4927
  })();
4863
4928
  if (this.#twistyPlayerProp === "alg") {
4864
- this.#twistyPlayer?.experimentalModel.puzzleAlg.addFreshListener(
4865
- (algWithIssues) => {
4866
- if (algWithIssues.issues.errors.length === 0) {
4867
- this.setAlgIssueClassForPuzzle(
4868
- algWithIssues.issues.warnings.length === 0 ? "none" : "warning"
4869
- );
4870
- const newAlg = algWithIssues.alg;
4871
- const oldAlg = Alg.fromString(this.algString);
4872
- if (!newAlg.isIdentical(oldAlg)) {
4873
- this.algString = newAlg.toString();
4874
- this.onInput();
4875
- } else {
4876
- }
4929
+ this.#twistyPlayer?.experimentalModel.puzzleAlg.addFreshListener((algWithIssues) => {
4930
+ if (algWithIssues.issues.errors.length === 0) {
4931
+ this.setAlgIssueClassForPuzzle(
4932
+ algWithIssues.issues.warnings.length === 0 ? "none" : "warning"
4933
+ );
4934
+ const newAlg = algWithIssues.alg;
4935
+ const oldAlg = Alg.fromString(this.algString);
4936
+ if (!newAlg.isIdentical(oldAlg)) {
4937
+ this.algString = newAlg.toString();
4938
+ this.onInput();
4877
4939
  } else {
4878
- this.setAlgIssueClassForPuzzle("error");
4879
4940
  }
4941
+ } else {
4942
+ this.setAlgIssueClassForPuzzle("error");
4880
4943
  }
4881
- );
4882
- this.model.leafToHighlight.addFreshListener(
4883
- async (highlightInfo) => {
4884
- if (highlightInfo === null) {
4885
- return;
4886
- }
4887
- const [indexer, timestampRequest] = await Promise.all([
4888
- await twistyPlayer.experimentalModel.indexer.get(),
4889
- await twistyPlayer.experimentalModel.timestampRequest.get()
4890
- ]);
4891
- if (timestampRequest === "opposite-anchor" && !this.#onInputHasFired) {
4892
- return;
4944
+ });
4945
+ this.model.leafToHighlight.addFreshListener(async (highlightInfo) => {
4946
+ if (highlightInfo === null) {
4947
+ return;
4948
+ }
4949
+ const [indexer, timestampRequest] = await Promise.all([
4950
+ await twistyPlayer.experimentalModel.indexer.get(),
4951
+ await twistyPlayer.experimentalModel.timestampRequest.get()
4952
+ ]);
4953
+ if (timestampRequest === "opposite-anchor" && !this.#onInputHasFired) {
4954
+ return;
4955
+ }
4956
+ const moveStartTimestamp = indexer.indexToMoveStartTimestamp(
4957
+ highlightInfo.leafInfo.idx
4958
+ );
4959
+ const duration = indexer.moveDuration(highlightInfo.leafInfo.idx);
4960
+ let newTimestamp;
4961
+ switch (highlightInfo.where) {
4962
+ case "before": {
4963
+ newTimestamp = moveStartTimestamp;
4964
+ break;
4893
4965
  }
4894
- const moveStartTimestamp = indexer.indexToMoveStartTimestamp(
4895
- highlightInfo.leafInfo.idx
4896
- );
4897
- const duration = indexer.moveDuration(highlightInfo.leafInfo.idx);
4898
- let newTimestamp;
4899
- switch (highlightInfo.where) {
4900
- case "before":
4901
- newTimestamp = moveStartTimestamp;
4902
- break;
4903
- case "start":
4904
- case "inside":
4905
- newTimestamp = moveStartTimestamp + duration / 4;
4906
- break;
4907
- case "end":
4908
- case "after":
4909
- newTimestamp = moveStartTimestamp + duration;
4910
- break;
4911
- default:
4912
- console.log("invalid where");
4913
- throw new Error("Invalid where!");
4966
+ case "start":
4967
+ case "inside": {
4968
+ newTimestamp = moveStartTimestamp + duration / 4;
4969
+ break;
4914
4970
  }
4915
- if (!this.debugNeverRequestTimestamp) {
4916
- twistyPlayer.experimentalModel.timestampRequest.set(newTimestamp);
4971
+ case "end":
4972
+ case "after": {
4973
+ newTimestamp = moveStartTimestamp + duration;
4974
+ break;
4917
4975
  }
4976
+ default:
4977
+ console.log("invalid where");
4978
+ throw new Error("Invalid where!");
4918
4979
  }
4919
- );
4980
+ if (!this.debugNeverRequestTimestamp) {
4981
+ twistyPlayer.experimentalModel.timestampRequest.set(newTimestamp);
4982
+ }
4983
+ });
4920
4984
  twistyPlayer.experimentalModel.currentLeavesSimplified.addFreshListener(
4921
4985
  async (currentLeavesSimplified) => {
4922
4986
  const indexer = await twistyPlayer.experimentalModel.indexer.get();
@@ -4941,16 +5005,18 @@ var TwistyAlgEditor = class extends ManagedCustomElement {
4941
5005
  this.twistyPlayer = elem;
4942
5006
  return;
4943
5007
  }
4944
- case ATTRIBUTE_PLACEHOLDER:
5008
+ case ATTRIBUTE_PLACEHOLDER: {
4945
5009
  this.placeholder = newValue;
4946
5010
  return;
4947
- case ATTRIBUTE_TWISTY_PLAYER_PROP:
5011
+ }
5012
+ case ATTRIBUTE_TWISTY_PLAYER_PROP: {
4948
5013
  if (this.#twistyPlayer) {
4949
5014
  console.log("cannot set prop");
4950
5015
  throw new Error("cannot set prop after twisty player");
4951
5016
  }
4952
5017
  this.#twistyPlayerProp = newValue;
4953
5018
  return;
5019
+ }
4954
5020
  }
4955
5021
  }
4956
5022
  static get observedAttributes() {
@@ -4964,7 +5030,8 @@ var TwistyAlgEditor = class extends ManagedCustomElement {
4964
5030
  customElementsShim.define("twisty-alg-editor", TwistyAlgEditor);
4965
5031
 
4966
5032
  // src/cubing/twisty/views/twizzle/TwizzleLink.css.ts
4967
- var twizzleLinkCSS = new CSSSource(`
5033
+ var twizzleLinkCSS = new CSSSource(
5034
+ `
4968
5035
  .wrapper {
4969
5036
  background: rgb(255, 245, 235);
4970
5037
  display: grid;
@@ -4997,20 +5064,21 @@ twisty-player {
4997
5064
  twisty-player + .heading {
4998
5065
  padding-top: 0.5em;
4999
5066
  }
5000
- `);
5067
+ `
5068
+ );
5001
5069
 
5002
5070
  // src/cubing/twisty/views/twizzle/url-params.ts
5003
5071
  function getConfigFromURL(prefix = "", url = location.href) {
5004
5072
  const paramMapping = {
5005
- "alg": "alg",
5073
+ alg: "alg",
5006
5074
  "setup-alg": "experimental-setup-alg",
5007
5075
  "setup-anchor": "experimental-setup-anchor",
5008
- "puzzle": "puzzle",
5009
- "stickering": "experimental-stickering",
5076
+ puzzle: "puzzle",
5077
+ stickering: "experimental-stickering",
5010
5078
  "puzzle-description": "experimental-puzzle-description",
5011
- "title": "experimental-title",
5079
+ title: "experimental-title",
5012
5080
  "video-url": "experimental-video-url",
5013
- "competition": "experimental-competition-id"
5081
+ competition: "experimental-competition-id"
5014
5082
  };
5015
5083
  const params = new URL(url).searchParams;
5016
5084
  const config = {};