cubing 0.32.1 → 0.33.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 (43) hide show
  1. package/dist/esm/{chunk-JVM7R4NB.js → chunk-ILVYXTHD.js} +6 -7
  2. package/dist/esm/{chunk-JVM7R4NB.js.map → chunk-ILVYXTHD.js.map} +2 -2
  3. package/dist/esm/{chunk-PXAYHEVD.js → chunk-OEHG3BF3.js} +6 -5
  4. package/dist/esm/chunk-OEHG3BF3.js.map +7 -0
  5. package/dist/esm/scramble/index.js +1 -2
  6. package/dist/esm/search/index.js +2 -3
  7. package/dist/esm/{search-dynamic-sgs-unofficial-2V7VKWGI.js → search-dynamic-sgs-unofficial-LORSO7LF.js} +2 -4
  8. package/dist/esm/{search-dynamic-sgs-unofficial-2V7VKWGI.js.map → search-dynamic-sgs-unofficial-LORSO7LF.js.map} +1 -1
  9. package/dist/esm/{search-dynamic-solve-4x4x4-RCBTBQF3.js → search-dynamic-solve-4x4x4-BJLOSTR2.js} +3 -5
  10. package/dist/esm/{search-dynamic-solve-4x4x4-RCBTBQF3.js.map → search-dynamic-solve-4x4x4-BJLOSTR2.js.map} +1 -1
  11. package/dist/esm/{search-dynamic-solve-fto-PZSGTVO7.js → search-dynamic-solve-fto-L5CX2BTQ.js} +2 -5
  12. package/dist/esm/{search-dynamic-solve-fto-PZSGTVO7.js.map → search-dynamic-solve-fto-L5CX2BTQ.js.map} +1 -1
  13. package/dist/esm/{search-dynamic-solve-kilominx-VRIE77AN.js → search-dynamic-solve-kilominx-FBEDWIPR.js} +2 -4
  14. package/dist/esm/{search-dynamic-solve-kilominx-VRIE77AN.js.map → search-dynamic-solve-kilominx-FBEDWIPR.js.map} +1 -1
  15. package/dist/esm/{search-dynamic-solve-master_tetraminx-EPWI375K.js → search-dynamic-solve-master_tetraminx-4R5R7LC5.js} +2 -5
  16. package/dist/esm/{search-dynamic-solve-master_tetraminx-EPWI375K.js.map → search-dynamic-solve-master_tetraminx-4R5R7LC5.js.map} +1 -1
  17. package/dist/esm/{search-dynamic-solve-sq1-PXS5SUQJ.js → search-dynamic-solve-sq1-CBPKRTVA.js} +2 -5
  18. package/dist/esm/{search-dynamic-solve-sq1-PXS5SUQJ.js.map → search-dynamic-solve-sq1-CBPKRTVA.js.map} +1 -1
  19. package/dist/esm/{search-worker-js-entry-Y6RQKL2N.js → search-worker-js-entry-M6ECI442.js} +17 -17
  20. package/dist/esm/{search-worker-js-entry-Y6RQKL2N.js.map → search-worker-js-entry-M6ECI442.js.map} +4 -4
  21. package/dist/esm/{search-worker-ts-entry-Q6HRXMHV.js → search-worker-ts-entry-TZANLWZL.js} +2 -2
  22. package/dist/esm/{search-worker-ts-entry-Q6HRXMHV.js.map → search-worker-ts-entry-TZANLWZL.js.map} +0 -0
  23. package/dist/esm/twisty/index.js +253 -32
  24. package/dist/esm/twisty/index.js.map +4 -4
  25. package/dist/types/{TwizzleLink-b28e5d4f.d.ts → TwizzleLink-3b4382cf.d.ts} +57 -11
  26. package/dist/types/puzzles/index.d.ts +2 -2
  27. package/dist/types/twisty/index.d.ts +2 -2
  28. package/package.json +2 -2
  29. package/dist/esm/alg/index.d.ts +0 -1
  30. package/dist/esm/bluetooth/index.d.ts +0 -1
  31. package/dist/esm/chunk-5AILXG4K.js +0 -60
  32. package/dist/esm/chunk-5AILXG4K.js.map +0 -7
  33. package/dist/esm/chunk-PXAYHEVD.js.map +0 -7
  34. package/dist/esm/kpuzzle/index.d.ts +0 -1
  35. package/dist/esm/notation/index.d.ts +0 -1
  36. package/dist/esm/protocol/index.d.ts +0 -1
  37. package/dist/esm/puzzle-geometry/index.d.ts +0 -1
  38. package/dist/esm/puzzles/index.d.ts +0 -1
  39. package/dist/esm/scramble/index.d.ts +0 -1
  40. package/dist/esm/search/index.d.ts +0 -1
  41. package/dist/esm/stream/index.d.ts +0 -1
  42. package/dist/esm/twisty/index.d.ts +0 -1
  43. package/dist/types/.DS_Store +0 -0
@@ -1244,12 +1244,20 @@ button:enabled {
1244
1244
  background-color: rgba(196, 196, 196, 0.75)
1245
1245
  }
1246
1246
 
1247
+ .dark-mode button:enabled {
1248
+ background-color: #88888888;
1249
+ }
1250
+
1247
1251
  button:disabled {
1248
1252
  background-color: rgba(0, 0, 0, 0.4);
1249
1253
  opacity: 0.25;
1250
1254
  pointer-events: none;
1251
1255
  }
1252
1256
 
1257
+ .dark-mode button:disabled {
1258
+ background-color: #ffffff44;
1259
+ }
1260
+
1253
1261
  button:enabled:hover {
1254
1262
  background-color: rgba(255, 255, 255, 0.75);
1255
1263
  box-shadow: 0 0 1em rgba(0, 0, 0, 0.25);
@@ -1398,11 +1406,11 @@ var buttonCommands = {
1398
1406
  "twizzle-link": true
1399
1407
  };
1400
1408
  var TwistyButtons = class extends ManagedCustomElement {
1401
- constructor(model, controller, fullscreenElement) {
1409
+ constructor(model, controller, defaultFullscreenElement) {
1402
1410
  super();
1403
1411
  this.model = model;
1404
1412
  this.controller = controller;
1405
- this.fullscreenElement = fullscreenElement;
1413
+ this.defaultFullscreenElement = defaultFullscreenElement;
1406
1414
  this.buttons = null;
1407
1415
  }
1408
1416
  connectedCallback() {
@@ -1419,6 +1427,9 @@ var TwistyButtons = class extends ManagedCustomElement {
1419
1427
  }
1420
1428
  this.buttons = buttons;
1421
1429
  this.model?.buttonAppearance.addFreshListener(this.update.bind(this));
1430
+ this.model?.twistySceneModel.darkMode.addFreshListener(
1431
+ this.updateDarkMode.bind(this)
1432
+ );
1422
1433
  }
1423
1434
  #onCommand(command) {
1424
1435
  switch (command) {
@@ -1461,16 +1472,18 @@ var TwistyButtons = class extends ManagedCustomElement {
1461
1472
  }
1462
1473
  }
1463
1474
  async onFullscreenButton() {
1464
- if (!this.fullscreenElement) {
1475
+ if (!this.defaultFullscreenElement) {
1465
1476
  throw new Error("Attempted to go fullscreen without an element.");
1466
1477
  }
1467
- if (documentFullscreenElement() === this.fullscreenElement) {
1478
+ if (documentFullscreenElement() === this.defaultFullscreenElement) {
1468
1479
  documentExitFullscreen();
1469
1480
  } else {
1470
1481
  this.buttons?.fullscreen.setIcon("exit-fullscreen");
1471
- requestFullscreen(this.fullscreenElement);
1482
+ requestFullscreen(
1483
+ await this.model?.twistySceneModel.fullscreenElement.get() ?? this.defaultFullscreenElement
1484
+ );
1472
1485
  const onFullscreen = () => {
1473
- if (documentFullscreenElement() !== this.fullscreenElement) {
1486
+ if (documentFullscreenElement() !== this.defaultFullscreenElement) {
1474
1487
  this.buttons?.fullscreen.setIcon("enter-fullscreen");
1475
1488
  window.removeEventListener("fullscreenchange", onFullscreen);
1476
1489
  }
@@ -1488,6 +1501,11 @@ var TwistyButtons = class extends ManagedCustomElement {
1488
1501
  button.hidden = !!info.hidden;
1489
1502
  }
1490
1503
  }
1504
+ updateDarkMode(darkMode) {
1505
+ for (const button of Object.values(this.buttons ?? {})) {
1506
+ button.updateDarkMode(darkMode);
1507
+ }
1508
+ }
1491
1509
  };
1492
1510
  customElementsShim.define("twisty-buttons", TwistyButtons);
1493
1511
  var TwistyButton = class extends ManagedCustomElement {
@@ -1500,6 +1518,9 @@ var TwistyButton = class extends ManagedCustomElement {
1500
1518
  buttonIcons
1501
1519
  );
1502
1520
  }
1521
+ updateDarkMode(darkMode) {
1522
+ this.contentWrapper.classList.toggle("dark-mode", darkMode === "dark");
1523
+ }
1503
1524
  connectedCallback() {
1504
1525
  this.addCSS(buttonCSS);
1505
1526
  this.addElement(this.htmlButton);
@@ -1527,12 +1548,16 @@ var twistyScrubberCSS = new CSSSource(
1527
1548
  overflow: hidden;
1528
1549
  backdrop-filter: blur(4px);
1529
1550
  -webkit-backdrop-filter: blur(4px);
1530
- background: rgba(196, 196, 196, 0.75)
1551
+ background: rgba(196, 196, 196, 0.75);
1531
1552
  }
1532
1553
 
1533
1554
  input:not(:disabled) {
1534
1555
  cursor: ew-resize;
1535
1556
  }
1557
+
1558
+ .wrapper.dark-mode {
1559
+ background: #666666;
1560
+ }
1536
1561
  `
1537
1562
  );
1538
1563
 
@@ -1591,6 +1616,12 @@ var TwistyScrubber = class extends ManagedCustomElement {
1591
1616
  async connectedCallback() {
1592
1617
  this.addCSS(twistyScrubberCSS);
1593
1618
  this.addElement(await this.inputElem());
1619
+ this.model?.twistySceneModel.darkMode.addFreshListener(
1620
+ this.updateDarkMode.bind(this)
1621
+ );
1622
+ }
1623
+ updateDarkMode(darkMode) {
1624
+ this.contentWrapper.classList.toggle("dark-mode", darkMode === "dark");
1594
1625
  }
1595
1626
  #inputElem = null;
1596
1627
  async inputElem() {
@@ -1768,7 +1799,8 @@ twisty-scrubber {
1768
1799
  background: rgba(196, 196, 196, 0.5);
1769
1800
  }
1770
1801
 
1771
- .wrapper.checkered {
1802
+ .wrapper.checkered,
1803
+ .wrapper.checkered-transparent {
1772
1804
  background-color: #EAEAEA;
1773
1805
  background-image: linear-gradient(45deg, #DDD 25%, transparent 25%, transparent 75%, #DDD 75%, #DDD),
1774
1806
  linear-gradient(45deg, #DDD 25%, transparent 25%, transparent 75%, #DDD 75%, #DDD);
@@ -1776,6 +1808,18 @@ twisty-scrubber {
1776
1808
  background-position: 0 0, 16px 16px;
1777
1809
  }
1778
1810
 
1811
+ .wrapper.checkered-transparent {
1812
+ background-color: #F4F4F4;
1813
+ background-image: linear-gradient(45deg, #DDDDDD88 25%, transparent 25%, transparent 75%, #DDDDDD88 75%, #DDDDDD88),
1814
+ linear-gradient(45deg, #DDDDDD88 25%, transparent 25%, transparent 75%, #DDDDDD88 75%, #DDDDDD88);
1815
+ }
1816
+
1817
+ .wrapper.dark-mode {
1818
+ background-color: #444;
1819
+ background-image: linear-gradient(45deg, #DDDDDD0b 25%, transparent 25%, transparent 75%, #DDDDDD0b 75%, #DDDDDD0b),
1820
+ linear-gradient(45deg, #DDDDDD0b 25%, transparent 25%, transparent 75%, #DDDDDD0b 75%, #DDDDDD0b);
1821
+ }
1822
+
1779
1823
  .visualization-wrapper > * {
1780
1824
  width: 100%;
1781
1825
  height: 100%;
@@ -3096,6 +3140,8 @@ var DetailedTimelineInfoProp = class extends TwistyPropDerived {
3096
3140
  }
3097
3141
  #requestedTimestampToMilliseconds(inputs) {
3098
3142
  switch (inputs.timestampRequest) {
3143
+ case "auto":
3144
+ return inputs.setupAnchor === "start" && inputs.setupAlg.alg.experimentalIsEmpty() ? inputs.timeRange.end : inputs.timeRange.start;
3099
3145
  case "start":
3100
3146
  return inputs.timeRange.start;
3101
3147
  case "end":
@@ -3146,6 +3192,7 @@ var TempoScaleProp = class extends TwistyPropSource {
3146
3192
 
3147
3193
  // src/cubing/twisty/model/props/timeline/TimestampRequestProp.ts
3148
3194
  var smartTimestamps = {
3195
+ auto: true,
3149
3196
  start: true,
3150
3197
  end: true,
3151
3198
  anchor: true,
@@ -3153,7 +3200,7 @@ var smartTimestamps = {
3153
3200
  };
3154
3201
  var TimestampRequestProp = class extends SimpleTwistyPropSource {
3155
3202
  getDefaultValue() {
3156
- return "opposite-anchor";
3203
+ return "auto";
3157
3204
  }
3158
3205
  set(v) {
3159
3206
  if (!this.validInput(v)) {
@@ -3244,6 +3291,13 @@ var VisualizationStrategyProp = class extends TwistyPropDerived {
3244
3291
  }
3245
3292
  };
3246
3293
 
3294
+ // src/cubing/twisty/model/props/puzzle/display/FaceletScaleProp.ts
3295
+ var FaceletScaleProp = class extends SimpleTwistyPropSource {
3296
+ getDefaultValue() {
3297
+ return "auto";
3298
+ }
3299
+ };
3300
+
3247
3301
  // src/cubing/twisty/model/props/puzzle/display/FoundationDisplayProp.ts
3248
3302
  var FoundationDisplayProp = class extends SimpleTwistyPropSource {
3249
3303
  getDefaultValue() {
@@ -3379,13 +3433,6 @@ var StickeringRequestProp = class extends SimpleTwistyPropSource {
3379
3433
  }
3380
3434
  };
3381
3435
 
3382
- // src/cubing/twisty/model/props/puzzle/display/FaceletScaleProp.ts
3383
- var FaceletScaleProp = class extends SimpleTwistyPropSource {
3384
- getDefaultValue() {
3385
- return "auto";
3386
- }
3387
- };
3388
-
3389
3436
  // src/cubing/twisty/model/props/puzzle/state/DragInputProp.ts
3390
3437
  var DragInputProp = class extends SimpleTwistyPropSource {
3391
3438
  getDefaultValue() {
@@ -3414,6 +3461,27 @@ var BackgroundProp = class extends SimpleTwistyPropSource {
3414
3461
  }
3415
3462
  };
3416
3463
 
3464
+ // src/cubing/twisty/model/props/viewer/DarkModeProp.ts
3465
+ var DarkModeProp = class extends TwistyPropDerived {
3466
+ derive(inputs) {
3467
+ return inputs.darkModeRequest === "dark" ? "dark" : "light";
3468
+ }
3469
+ };
3470
+
3471
+ // src/cubing/twisty/model/props/viewer/DarkModeRequestProp.ts
3472
+ var DarkModeRequstProp = class extends SimpleTwistyPropSource {
3473
+ getDefaultValue() {
3474
+ return "auto";
3475
+ }
3476
+ };
3477
+
3478
+ // src/cubing/twisty/model/props/viewer/DOMElementReferenceProp.ts
3479
+ var DOMElementReferenceProp = class extends SimpleTwistyPropSource {
3480
+ getDefaultValue() {
3481
+ return null;
3482
+ }
3483
+ };
3484
+
3417
3485
  // src/cubing/twisty/model/props/viewer/LatitudeLimit.ts
3418
3486
  var DEFAULT_LATITUDE_LIMIT = 35;
3419
3487
  var LatitudeLimitProp = class extends SimpleTwistyPropSource {
@@ -3534,9 +3602,11 @@ var TwistySceneModel = class {
3534
3602
  constructor(twistyPlayerModel) {
3535
3603
  this.twistyPlayerModel = twistyPlayerModel;
3536
3604
  this.background = new BackgroundProp();
3605
+ this.darkModeRequest = new DarkModeRequstProp();
3537
3606
  this.dragInput = new DragInputProp();
3538
3607
  this.foundationDisplay = new FoundationDisplayProp();
3539
3608
  this.foundationStickerSpriteURL = new URLProp();
3609
+ this.fullscreenElement = new DOMElementReferenceProp();
3540
3610
  this.hintFacelet = new HintFaceletProp();
3541
3611
  this.hintStickerSpriteURL = new URLProp();
3542
3612
  this.initialHintFaceletsAnimation = new InitialHintFaceletsAnimationProp();
@@ -3547,6 +3617,7 @@ var TwistySceneModel = class {
3547
3617
  this.stickeringMaskRequest = new StickeringMaskRequestProp();
3548
3618
  this.stickeringRequest = new StickeringRequestProp();
3549
3619
  this.faceletScale = new FaceletScaleProp();
3620
+ this.darkMode = new DarkModeProp({ darkModeRequest: this.darkModeRequest });
3550
3621
  this.foundationStickerSprite = new SpriteProp({
3551
3622
  spriteURL: this.foundationStickerSpriteURL
3552
3623
  });
@@ -3653,7 +3724,8 @@ var TwistyPlayerModel = class {
3653
3724
  {
3654
3725
  timestampRequest: this.timestampRequest,
3655
3726
  timeRange: this.timeRange,
3656
- setupAnchor: this.setupAnchor
3727
+ setupAnchor: this.setupAnchor,
3728
+ setupAlg: this.setupAlg
3657
3729
  }
3658
3730
  );
3659
3731
  this.coarseTimelineInfo = new CoarseTimelineInfoProp({
@@ -3691,7 +3763,8 @@ var TwistyPlayerModel = class {
3691
3763
  alg,
3692
3764
  setup,
3693
3765
  anchor,
3694
- experimentalStickeringRequest
3766
+ experimentalStickeringRequest,
3767
+ experimentalTitle
3695
3768
  ] = await Promise.all([
3696
3769
  this.viewerLink.get(),
3697
3770
  this.puzzleID.get(),
@@ -3699,7 +3772,8 @@ var TwistyPlayerModel = class {
3699
3772
  this.alg.get(),
3700
3773
  this.setupAlg.get(),
3701
3774
  this.setupAnchor.get(),
3702
- this.twistySceneModel.stickeringRequest.get()
3775
+ this.twistySceneModel.stickeringRequest.get(),
3776
+ this.twistySceneModel.twistyPlayerModel.title.get()
3703
3777
  ]);
3704
3778
  const isExplorer = viewerLink === "experimental-twizzle-explorer";
3705
3779
  const url = new URL(
@@ -3725,6 +3799,9 @@ var TwistyPlayerModel = class {
3725
3799
  } else if (puzzleID !== "3x3x3") {
3726
3800
  url.searchParams.set("puzzle", puzzleID);
3727
3801
  }
3802
+ if (experimentalTitle) {
3803
+ url.searchParams.set("title", experimentalTitle);
3804
+ }
3728
3805
  return url.toString();
3729
3806
  }
3730
3807
  experimentalAddAlgLeaf(algLeaf, options) {
@@ -3874,6 +3951,12 @@ var TwistyPlayerSettable = class extends ManagedCustomElement {
3874
3951
  get background() {
3875
3952
  throw err("background");
3876
3953
  }
3954
+ set darkMode(darkMode) {
3955
+ this.experimentalModel.twistySceneModel.darkModeRequest.set(darkMode);
3956
+ }
3957
+ get darkMode() {
3958
+ throw err("darkMode");
3959
+ }
3877
3960
  set controlPanel(newControlPanel) {
3878
3961
  this.experimentalModel.controlPanel.set(newControlPanel);
3879
3962
  }
@@ -3978,6 +4061,12 @@ var TwistyPlayerSettable = class extends ManagedCustomElement {
3978
4061
  get experimentalHintSprite() {
3979
4062
  throw err("experimentalHintSprite");
3980
4063
  }
4064
+ set fullscreenElement(element) {
4065
+ this.experimentalModel.twistySceneModel.fullscreenElement.set(element);
4066
+ }
4067
+ get fullscreenElement() {
4068
+ throw err("fullscreenElement");
4069
+ }
3981
4070
  set experimentalInitialHintFaceletsAnimation(anim) {
3982
4071
  this.experimentalModel.twistySceneModel.initialHintFaceletsAnimation.set(
3983
4072
  anim
@@ -4024,6 +4113,7 @@ var twistyPlayerAttributeMap = {
4024
4113
  "experimental-stickering": "experimentalStickering",
4025
4114
  "experimental-stickering-mask-orbits": "experimentalStickeringMaskOrbits",
4026
4115
  background: "background",
4116
+ "dark-mode": "darkMode",
4027
4117
  "control-panel": "controlPanel",
4028
4118
  "back-view": "backView",
4029
4119
  "experimental-initial-hint-facelets-animation": "experimentalInitialHintFaceletsAnimation",
@@ -4117,7 +4207,19 @@ var TwistyPlayer = class extends TwistyPlayerSettable {
4117
4207
  (backgroundTheme) => {
4118
4208
  this.contentWrapper.classList.toggle(
4119
4209
  "checkered",
4120
- backgroundTheme !== "none"
4210
+ ["auto", "checkered"].includes(backgroundTheme)
4211
+ );
4212
+ this.contentWrapper.classList.toggle(
4213
+ "checkered-transparent",
4214
+ backgroundTheme === "checkered-transparent"
4215
+ );
4216
+ }
4217
+ );
4218
+ this.experimentalModel.twistySceneModel.darkMode.addFreshListener(
4219
+ (darkModeTheme) => {
4220
+ this.contentWrapper.classList.toggle(
4221
+ "dark-mode",
4222
+ ["dark"].includes(darkModeTheme)
4121
4223
  );
4122
4224
  }
4123
4225
  );
@@ -5140,7 +5242,7 @@ var TwistyAlgEditor = class extends ManagedCustomElement {
5140
5242
  await twistyPlayer.experimentalModel.indexer.get(),
5141
5243
  await twistyPlayer.experimentalModel.timestampRequest.get()
5142
5244
  ]);
5143
- if (timestampRequest === "opposite-anchor" && !this.#onInputHasFired) {
5245
+ if (timestampRequest === "auto" && !this.#onInputHasFired) {
5144
5246
  return;
5145
5247
  }
5146
5248
  const moveStartTimestamp = indexer.indexToMoveStartTimestamp(
@@ -5238,6 +5340,8 @@ var twizzleLinkCSS = new CSSSource(
5238
5340
  background: rgba(255, 230, 210, 1);
5239
5341
  font-weight: bold;
5240
5342
  padding: 0.25em 0.5em;
5343
+ display: grid;
5344
+ grid-template-columns: 1fr auto;
5241
5345
  }
5242
5346
 
5243
5347
  .heading.title {
@@ -5246,6 +5350,11 @@ var twizzleLinkCSS = new CSSSource(
5246
5350
  white-space: pre;
5247
5351
  }
5248
5352
 
5353
+ .heading a {
5354
+ text-decoration: none;
5355
+ color: inherit;
5356
+ }
5357
+
5249
5358
  twisty-player {
5250
5359
  width: 100%;
5251
5360
  resize: vertical;
@@ -5255,8 +5364,55 @@ twisty-player {
5255
5364
  twisty-player + .heading {
5256
5365
  padding-top: 0.5em;
5257
5366
  }
5367
+
5368
+ twisty-alg-viewer {
5369
+ display: inline-block;
5370
+ }
5371
+
5372
+ .wrapper:fullscreen {
5373
+ width: 100%;
5374
+ height: 100%;
5375
+ }
5376
+
5377
+ .wrapper:fullscreen twisty-player {
5378
+ height: 50vh;
5379
+ }
5380
+
5381
+ .wrapper:fullscreen .scrollable-region {
5382
+ height: 50vh
5383
+ }
5258
5384
  `
5259
5385
  );
5386
+ var twizzleLinkForumTweaksCSS = new CSSSource(`
5387
+ .wrapper {
5388
+ background: white;
5389
+ }
5390
+
5391
+ .heading {
5392
+ background: #4285f422;
5393
+ }
5394
+
5395
+ .scrollable-region {
5396
+ max-height: 280px;
5397
+ overflow-y: auto;
5398
+ }
5399
+
5400
+ .wrapper.dark-mode {
5401
+ background: #262626;
5402
+ color: #929292;
5403
+ border-color: #FFFFFF44;
5404
+ color-scheme: dark;
5405
+ }
5406
+
5407
+ .wrapper.dark-mode .heading {
5408
+ background: #1d1d1d;
5409
+ color: #ececec;
5410
+ }
5411
+
5412
+ .heading.title {
5413
+ background: none;
5414
+ }
5415
+ `);
5260
5416
 
5261
5417
  // src/cubing/twisty/views/twizzle/url-params.ts
5262
5418
  function getConfigFromURL(prefix = "", url = location.href) {
@@ -5285,8 +5441,9 @@ function getConfigFromURL(prefix = "", url = location.href) {
5285
5441
 
5286
5442
  // src/cubing/twisty/views/twizzle/TwizzleLink.ts
5287
5443
  var TwizzleLink = class extends ManagedCustomElement {
5288
- constructor() {
5444
+ constructor(options) {
5289
5445
  super({ mode: "open" });
5446
+ this.options = options;
5290
5447
  this.twistyPlayer = null;
5291
5448
  this.a = null;
5292
5449
  }
@@ -5300,13 +5457,20 @@ var TwizzleLink = class extends ManagedCustomElement {
5300
5457
  span.title = "Could not show a player for link";
5301
5458
  this.addElement(this.a);
5302
5459
  }
5303
- if (this.#cssElem) {
5304
- this.#cssElem.remove();
5305
- }
5460
+ this.#cssElem?.remove();
5461
+ this.#cssCDNForumTweaksElem?.remove();
5306
5462
  }
5307
5463
  #cssElem;
5464
+ #cssCDNForumTweaksElem;
5465
+ #scrollableRegion;
5308
5466
  async connectedCallback() {
5467
+ if (this.options?.darkMode) {
5468
+ this.contentWrapper.classList.add("dark-mode");
5469
+ }
5309
5470
  this.#cssElem = this.addCSS(twizzleLinkCSS);
5471
+ if (this.options?.cdnForumTweaks) {
5472
+ this.addCSS(twizzleLinkForumTweaksCSS);
5473
+ }
5310
5474
  this.a = this.querySelector("a");
5311
5475
  if (!this.a) {
5312
5476
  return;
@@ -5327,23 +5491,39 @@ var TwizzleLink = class extends ManagedCustomElement {
5327
5491
  }
5328
5492
  this.twistyPlayer = this.addElement(
5329
5493
  new TwistyPlayer({
5494
+ background: this.options?.cdnForumTweaks ? "checkered-transparent" : "checkered",
5495
+ darkMode: this.options?.darkMode ? "dark" : "light",
5330
5496
  ...config,
5331
5497
  viewerLink: isExplorer ? "experimental-twizzle-explorer" : "auto"
5332
5498
  })
5333
5499
  );
5500
+ this.twistyPlayer.fullscreenElement = this.contentWrapper;
5501
+ if (config.experimentalTitle) {
5502
+ this.twistyPlayer.experimentalTitle = config.experimentalTitle;
5503
+ }
5504
+ this.#scrollableRegion = this.addElement(document.createElement("div"));
5505
+ this.#scrollableRegion.classList.add("scrollable-region");
5334
5506
  if (config.experimentalTitle) {
5335
5507
  this.addHeading(config.experimentalTitle).classList.add("title");
5336
5508
  }
5337
5509
  if (config.experimentalSetupAlg) {
5338
- this.addHeading("Setup");
5339
- const setupAlgDiv = this.addElement(document.createElement("div"));
5510
+ this.addHeading(
5511
+ "Setup",
5512
+ async () => (await this.twistyPlayer?.experimentalModel.setupAlg.get())?.alg.toString() ?? null
5513
+ );
5514
+ const setupAlgDiv = this.#scrollableRegion.appendChild(
5515
+ document.createElement("div")
5516
+ );
5340
5517
  setupAlgDiv.classList.add("setup-alg");
5341
5518
  setupAlgDiv.textContent = new Alg(
5342
5519
  config.experimentalSetupAlg
5343
5520
  ).toString();
5344
5521
  }
5345
- this.addHeading("Moves");
5346
- const twistyAlgViewer = this.addElement(
5522
+ this.addHeading(
5523
+ "Moves",
5524
+ async () => (await this.twistyPlayer?.experimentalModel.alg.get())?.alg.toString() ?? null
5525
+ );
5526
+ const twistyAlgViewer = this.#scrollableRegion.appendChild(
5347
5527
  new TwistyAlgViewer({ twistyPlayer: this.twistyPlayer })
5348
5528
  );
5349
5529
  twistyAlgViewer.part.add("twisty-alg-viewer");
@@ -5351,14 +5531,55 @@ var TwizzleLink = class extends ManagedCustomElement {
5351
5531
  this.fallback();
5352
5532
  }
5353
5533
  }
5354
- addHeading(text) {
5355
- const headingDiv = this.addElement(document.createElement("div"));
5534
+ addHeading(text, getTextToCopy) {
5535
+ const headingDiv = this.#scrollableRegion.appendChild(
5536
+ document.createElement("div")
5537
+ );
5356
5538
  headingDiv.classList.add("heading");
5357
5539
  headingDiv.textContent = text;
5540
+ if (getTextToCopy) {
5541
+ headingDiv.textContent += " ";
5542
+ const a = headingDiv.appendChild(document.createElement("a"));
5543
+ a.textContent = "\u{1F4CB}";
5544
+ a.href = "#";
5545
+ a.title = "Copy to clipboard";
5546
+ async function setAndClear(text2) {
5547
+ a.textContent = text2;
5548
+ await new Promise((resolve) => setTimeout(resolve, 2e3));
5549
+ if (a.textContent === text2) {
5550
+ a.textContent = "\u{1F4CB}";
5551
+ }
5552
+ }
5553
+ a.addEventListener("click", async (e) => {
5554
+ e.preventDefault();
5555
+ a.textContent = "\u2026\u{1F4CB}";
5556
+ const textToCopy = await getTextToCopy();
5557
+ if (textToCopy) {
5558
+ try {
5559
+ await navigator.clipboard.writeText(textToCopy);
5560
+ setAndClear("\u2705\u{1F4CB}");
5561
+ } catch (e2) {
5562
+ setAndClear("\u274C\u{1F4CB}");
5563
+ throw e2;
5564
+ }
5565
+ } else {
5566
+ setAndClear("\u274C\u{1F4CB}");
5567
+ }
5568
+ });
5569
+ }
5358
5570
  return headingDiv;
5359
5571
  }
5360
5572
  };
5361
5573
  customElementsShim.define("twizzle-link", TwizzleLink);
5574
+ var TwizzleForumLink = class extends TwizzleLink {
5575
+ constructor() {
5576
+ super({
5577
+ cdnForumTweaks: true,
5578
+ darkMode: document.documentElement.classList.contains("style-dark")
5579
+ });
5580
+ }
5581
+ };
5582
+ customElementsShim.define("twizzle-forum-link", TwizzleForumLink);
5362
5583
  export {
5363
5584
  NO_VALUE as EXPERIMENTAL_PROP_NO_VALUE,
5364
5585
  KPuzzleSVGWrapper as ExperimentalKPuzzleSVGWrapper,
@@ -5367,7 +5588,7 @@ export {
5367
5588
  TwistyAlgEditor,
5368
5589
  TwistyAlgViewer,
5369
5590
  TwistyPlayer,
5370
- TwizzleLink,
5591
+ TwizzleForumLink as TwizzleLink,
5371
5592
  backViewLayouts,
5372
5593
  setTwistyDebug
5373
5594
  };