dsh-skin-galactic-opera 0.1.2 → 0.1.4

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.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,22 @@
2
2
 
3
3
  All notable changes to this package will be documented in this file.
4
4
 
5
+ ## 0.1.4 - 2026-08-28
6
+
7
+ ### Fixed
8
+
9
+ - Restores the top-right satellite's original 0.1.2 elliptical orbit behavior by excluding satellite and orbit animations from typing low-distraction pause rules.
10
+
11
+ ## 0.1.3 - 2026-08-27
12
+
13
+ ### Added
14
+
15
+ - Triangle collapse/expand control that complements the bottom-right telemetry panel corner cut and remembers its state.
16
+
17
+ ### Changed
18
+
19
+ - Reduces visual and JavaScript activity while typing by pausing high-motion skin effects, scanner updates, pointer parallax, click pulses on editable controls, and telemetry rescans during active input.
20
+
5
21
  ## 0.1.2 - 2026-08-27
6
22
 
7
23
  ### Fixed
package/lib/client.js CHANGED
@@ -139,6 +139,38 @@ body.dsh-skin-galactic-opera #root::before {
139
139
  will-change: transform;
140
140
  }
141
141
 
142
+ body.dsh-skin-galactic-opera.dsh-skin-input-active::before,
143
+ body.dsh-skin-galactic-opera.dsh-skin-input-active::after,
144
+ body.dsh-skin-galactic-opera.dsh-skin-input-active #root::before {
145
+ animation-play-state: paused !important;
146
+ }
147
+
148
+ body.dsh-skin-galactic-opera.dsh-skin-input-active::before {
149
+ opacity: 0.28;
150
+ }
151
+
152
+ body.dsh-skin-galactic-opera.dsh-skin-input-active::after {
153
+ opacity: 0.12;
154
+ }
155
+
156
+ body.dsh-skin-galactic-opera.dsh-skin-input-active #root::before {
157
+ opacity: 0.10;
158
+ transform: none;
159
+ will-change: auto;
160
+ }
161
+
162
+ body.dsh-skin-galactic-opera.dsh-skin-input-active .dsh-skin-galactic-opera-decor {
163
+ opacity: 0.28;
164
+ }
165
+
166
+ body.dsh-skin-galactic-opera.dsh-skin-input-active :is(.dsh-skin-nebula-core, .dsh-skin-energy, .dsh-skin-comet, .dsh-skin-starfighter, .dsh-skin-mission-crawl, .dsh-skin-scanner, .dsh-skin-scanner::after, .dsh-skin-route-map) {
167
+ animation-play-state: paused !important;
168
+ }
169
+
170
+ body.dsh-skin-galactic-opera.dsh-skin-input-active :is(.dsh-skin-nebula-core, .dsh-skin-energy, .dsh-skin-comet, .dsh-skin-starfighter, .dsh-skin-mission-crawl) {
171
+ opacity: 0.08 !important;
172
+ }
173
+
142
174
  body.dsh-skin-galactic-opera #root > *,
143
175
  body.dsh-skin-galactic-opera main,
144
176
  body.dsh-skin-galactic-opera aside,
@@ -614,6 +646,13 @@ body.dsh-skin-galactic-opera :is(pre, code, textarea, input, select, [class*="me
614
646
  inset 0 0 20px rgba(255, 207, 92, 0.035) !important;
615
647
  }
616
648
 
649
+ body.dsh-skin-galactic-opera.dsh-skin-input-active :is(textarea, input, [contenteditable="true"]):hover,
650
+ body.dsh-skin-galactic-opera.dsh-skin-input-active :is(textarea, input, [contenteditable="true"]):focus,
651
+ body.dsh-skin-galactic-opera.dsh-skin-input-active :is(textarea, input, [contenteditable="true"]):focus-within {
652
+ outline: none !important;
653
+ box-shadow: none !important;
654
+ }
655
+
617
656
  body.dsh-skin-galactic-opera ::selection {
618
657
  color: #03040b;
619
658
  background: rgba(255, 207, 92, 0.86);
@@ -662,6 +701,23 @@ body.dsh-skin-galactic-opera .dsh-skin-telemetry-panel {
662
701
  pointer-events: none;
663
702
  }
664
703
 
704
+ body.dsh-skin-galactic-opera .dsh-skin-telemetry-panel[data-collapsed="true"] {
705
+ width: 24px;
706
+ min-height: 24px;
707
+ padding: 0;
708
+ border-color: transparent;
709
+ background: transparent;
710
+ box-shadow: none;
711
+ backdrop-filter: none;
712
+ -webkit-backdrop-filter: none;
713
+ }
714
+
715
+ body.dsh-skin-galactic-opera .dsh-skin-telemetry-panel[data-collapsed="true"]::before,
716
+ body.dsh-skin-galactic-opera .dsh-skin-telemetry-panel[data-collapsed="true"]::after,
717
+ body.dsh-skin-galactic-opera .dsh-skin-telemetry-panel[data-collapsed="true"] .dsh-skin-telemetry-content {
718
+ display: none !important;
719
+ }
720
+
665
721
  body.dsh-skin-galactic-opera .dsh-skin-telemetry-panel::before {
666
722
  content: "TELEMETRY";
667
723
  position: absolute;
@@ -685,6 +741,71 @@ body.dsh-skin-galactic-opera .dsh-skin-telemetry-panel::after {
685
741
  pointer-events: none;
686
742
  }
687
743
 
744
+ body.dsh-skin-galactic-opera .dsh-skin-telemetry-content {
745
+ position: relative;
746
+ z-index: 1;
747
+ display: flex;
748
+ flex-direction: column;
749
+ gap: 4px;
750
+ }
751
+
752
+ body.dsh-skin-galactic-opera .dsh-skin-telemetry-toggle[hidden] {
753
+ display: none !important;
754
+ }
755
+
756
+ body.dsh-skin-galactic-opera .dsh-skin-telemetry-toggle {
757
+ position: fixed;
758
+ right: max(18px, 2.4vmin);
759
+ bottom: max(18px, 2.4vmin);
760
+ z-index: 2147483645;
761
+ width: 24px;
762
+ height: 24px;
763
+ padding: 0;
764
+ border: 1px solid rgba(255,207,92,0.78);
765
+ border-left-color: rgba(125,227,255,0.54);
766
+ border-top-color: rgba(125,227,255,0.32);
767
+ clip-path: polygon(100% 0, 100% 100%, 0 100%);
768
+ cursor: pointer;
769
+ pointer-events: auto;
770
+ color: transparent;
771
+ background:
772
+ linear-gradient(135deg, transparent 0 43%, rgba(7,12,32,0.88) 44% 100%),
773
+ radial-gradient(circle at 72% 74%, rgba(255,207,92,0.98), rgba(125,227,255,0.72) 38%, rgba(255,71,120,0.34) 68%, transparent 72%);
774
+ box-shadow:
775
+ 0 0 0 1px rgba(3,4,11,0.48),
776
+ 0 0 18px rgba(125,227,255,0.42),
777
+ inset -5px -5px 13px rgba(255,207,92,0.18) !important;
778
+ }
779
+
780
+ body.dsh-skin-galactic-opera .dsh-skin-telemetry-toggle::before {
781
+ content: "";
782
+ position: absolute;
783
+ right: 5px;
784
+ bottom: 5px;
785
+ width: 7px;
786
+ height: 7px;
787
+ border-right: 2px solid rgba(248,251,255,0.95);
788
+ border-bottom: 2px solid rgba(248,251,255,0.95);
789
+ filter: drop-shadow(0 0 5px rgba(255,207,92,0.82));
790
+ }
791
+
792
+ body.dsh-skin-galactic-opera .dsh-skin-telemetry-toggle[data-collapsed="true"]::before {
793
+ right: 7px;
794
+ bottom: 7px;
795
+ border-right: 0;
796
+ border-bottom: 0;
797
+ border-left: 2px solid rgba(248,251,255,0.95);
798
+ border-top: 2px solid rgba(248,251,255,0.95);
799
+ }
800
+
801
+ body.dsh-skin-galactic-opera .dsh-skin-telemetry-toggle:hover {
802
+ box-shadow:
803
+ 0 0 0 1px rgba(255,207,92,0.62),
804
+ 0 0 24px rgba(255,207,92,0.52),
805
+ 0 0 38px rgba(125,227,255,0.30),
806
+ inset -5px -5px 15px rgba(255,207,92,0.26) !important;
807
+ }
808
+
688
809
  body.dsh-skin-galactic-opera .dsh-skin-telemetry-row {
689
810
  position: relative;
690
811
  z-index: 1;
@@ -952,11 +1073,13 @@ body.dsh-skin-galactic-opera .dsh-skin-telemetry-value-full {
952
1073
  if (typeof document === "undefined" || typeof window === "undefined" || decor === undefined) return () => {};
953
1074
  let frame = 0;
954
1075
  let sweepFrame = 0;
1076
+ let sweepTimer = 0;
955
1077
  let latestX = window.innerWidth / 2;
956
1078
  let latestY = window.innerHeight / 2;
957
1079
  let targetAngle = 0;
958
1080
  let pulseIndex = 0;
959
1081
  let hyperspaceTimer;
1082
+ let inputFocusTimer;
960
1083
  let lastHyperspaceAt = 0;
961
1084
  const scannerTarget = decor.querySelector(".dsh-skin-scanner-target");
962
1085
  const scannerStartedAt = performance.now();
@@ -983,8 +1106,19 @@ body.dsh-skin-galactic-opera .dsh-skin-telemetry-value-full {
983
1106
  document.body.style.setProperty("--dsh-skin-scanner-dot-y", `${Math.round(scannerCenterY + Math.sin(angle) * radius)}px`);
984
1107
  }
985
1108
  };
1109
+ const isTypingActive = () => document.activeElement instanceof Element && isEditableTarget(document.activeElement);
1110
+ const setInputActive = (active) => {
1111
+ window.clearTimeout(inputFocusTimer);
1112
+ if (active) {
1113
+ document.body.classList.add("dsh-skin-input-active");
1114
+ } else {
1115
+ inputFocusTimer = window.setTimeout(() => {
1116
+ document.body.classList.remove("dsh-skin-input-active");
1117
+ }, 160);
1118
+ }
1119
+ };
986
1120
  const onPointerMove = (event) => {
987
- if (isReducedMotion()) return;
1121
+ if (isReducedMotion() || isTypingActive()) return;
988
1122
  latestX = event.clientX;
989
1123
  latestY = event.clientY;
990
1124
  if (frame === 0) frame = requestAnimationFrame(updatePointer);
@@ -1001,7 +1135,7 @@ body.dsh-skin-galactic-opera .dsh-skin-telemetry-value-full {
1001
1135
  }, 900);
1002
1136
  };
1003
1137
  const onPointerDown = (event) => {
1004
- if (isReducedMotion()) return;
1138
+ if (isReducedMotion() || isEditableTarget(event.target)) return;
1005
1139
  const pulse = document.createElement("span");
1006
1140
  pulse.className = "dsh-skin-pulse";
1007
1141
  pulse.style.setProperty("--dsh-skin-pulse-x", `${event.clientX}px`);
@@ -1020,9 +1154,18 @@ body.dsh-skin-galactic-opera .dsh-skin-telemetry-value-full {
1020
1154
  if (event.code !== "Enter" || event.shiftKey || event.altKey) return;
1021
1155
  window.setTimeout(triggerHyperspace, 40);
1022
1156
  };
1157
+ const onFocusIn = (event) => {
1158
+ if (isEditableTarget(event.target)) setInputActive(true);
1159
+ };
1160
+ const onFocusOut = (event) => {
1161
+ if (isEditableTarget(event.target)) setInputActive(false);
1162
+ };
1023
1163
  const sweepLoop = () => {
1164
+ sweepFrame = 0;
1165
+ sweepTimer = 0;
1166
+ const typing = isTypingActive();
1024
1167
  if (scannerTarget instanceof HTMLElement) {
1025
- if (isReducedMotion()) {
1168
+ if (isReducedMotion() || typing) {
1026
1169
  scannerTarget.removeAttribute("data-lit");
1027
1170
  } else {
1028
1171
  // The scanner disk rotates once every 7s. Offset roughly matches the bright conic wedge.
@@ -1032,19 +1175,28 @@ body.dsh-skin-galactic-opera .dsh-skin-telemetry-value-full {
1032
1175
  else scannerTarget.removeAttribute("data-lit");
1033
1176
  }
1034
1177
  }
1035
- sweepFrame = requestAnimationFrame(sweepLoop);
1178
+ if (typing) sweepTimer = window.setTimeout(sweepLoop, 300);
1179
+ else sweepFrame = requestAnimationFrame(sweepLoop);
1036
1180
  };
1037
1181
  updatePointer();
1038
1182
  sweepFrame = requestAnimationFrame(sweepLoop);
1039
1183
  document.addEventListener("pointermove", onPointerMove, { passive: true });
1040
1184
  document.addEventListener("pointerdown", onPointerDown, { passive: true });
1041
1185
  document.addEventListener("keydown", onKeyDown);
1186
+ document.addEventListener("focusin", onFocusIn);
1187
+ document.addEventListener("focusout", onFocusOut);
1188
+ if (isTypingActive()) setInputActive(true);
1042
1189
  return () => {
1043
1190
  document.removeEventListener("pointermove", onPointerMove);
1044
1191
  document.removeEventListener("pointerdown", onPointerDown);
1045
1192
  document.removeEventListener("keydown", onKeyDown);
1193
+ document.removeEventListener("focusin", onFocusIn);
1194
+ document.removeEventListener("focusout", onFocusOut);
1195
+ window.clearTimeout(inputFocusTimer);
1196
+ document.body.classList.remove("dsh-skin-input-active");
1046
1197
  if (frame !== 0) cancelAnimationFrame(frame);
1047
1198
  if (sweepFrame !== 0) cancelAnimationFrame(sweepFrame);
1199
+ if (sweepTimer !== 0) window.clearTimeout(sweepTimer);
1048
1200
  if (scannerTarget instanceof HTMLElement) scannerTarget.removeAttribute("data-lit");
1049
1201
  window.clearTimeout(hyperspaceTimer);
1050
1202
  document.body.classList.remove("dsh-skin-hyperspace");
@@ -1063,11 +1215,24 @@ body.dsh-skin-galactic-opera .dsh-skin-telemetry-value-full {
1063
1215
  let currentSources = new Set();
1064
1216
  let lastText = "";
1065
1217
  let frame = 0;
1218
+ let collapsed = false;
1219
+ try {
1220
+ collapsed = window.localStorage?.getItem("dsh-skin-galactic-opera:telemetry-collapsed") === "true";
1221
+ } catch {
1222
+ collapsed = false;
1223
+ }
1066
1224
  const panel = document.createElement("div");
1067
1225
  panel.className = "dsh-skin-telemetry-panel";
1068
1226
  panel.setAttribute("aria-hidden", "true");
1069
1227
  panel.hidden = true;
1070
- document.body.appendChild(panel);
1228
+ const content = document.createElement("div");
1229
+ content.className = "dsh-skin-telemetry-content";
1230
+ panel.append(content);
1231
+ const toggle = document.createElement("button");
1232
+ toggle.type = "button";
1233
+ toggle.className = "dsh-skin-telemetry-toggle";
1234
+ toggle.hidden = true;
1235
+ document.body.append(panel, toggle);
1071
1236
  const isSkippable = (element) => element.closest(skipSelector) !== null;
1072
1237
  const hasEditableDescendant = (element) => element.querySelector(editableDescendantSelector) !== null;
1073
1238
  const getTelemetryText = (element) => (element.innerText || element.textContent || "").replace(/\s+/g, " ").trim();
@@ -1196,10 +1361,30 @@ body.dsh-skin-galactic-opera .dsh-skin-telemetry-value-full {
1196
1361
  const fixedRows = [roundRow, durationRow, firstTokenRow, cacheRow, inputOutputRow].filter(Boolean);
1197
1362
  return fixedRows.slice(0, 5);
1198
1363
  };
1364
+ const setCollapsed = (nextCollapsed) => {
1365
+ collapsed = nextCollapsed;
1366
+ panel.dataset.collapsed = String(collapsed);
1367
+ toggle.dataset.collapsed = String(collapsed);
1368
+ toggle.setAttribute("aria-expanded", String(!collapsed));
1369
+ toggle.setAttribute("aria-label", collapsed ? "展开 telemetry 面板" : "收缩 telemetry 面板");
1370
+ toggle.title = collapsed ? "展开 telemetry 面板" : "收缩 telemetry 面板";
1371
+ try {
1372
+ window.localStorage?.setItem("dsh-skin-galactic-opera:telemetry-collapsed", String(collapsed));
1373
+ } catch {
1374
+ // Storage may be unavailable in private or restricted contexts.
1375
+ }
1376
+ };
1377
+ setCollapsed(collapsed);
1378
+ toggle.addEventListener("click", (event) => {
1379
+ event.preventDefault();
1380
+ event.stopPropagation();
1381
+ setCollapsed(!collapsed);
1382
+ });
1199
1383
  const renderPanel = (text) => {
1200
1384
  const rows = splitTelemetryRows(text);
1201
1385
  panel.hidden = rows.length === 0;
1202
- panel.replaceChildren(...rows.map((text) => {
1386
+ toggle.hidden = rows.length === 0;
1387
+ content.replaceChildren(...rows.map((text) => {
1203
1388
  const row = document.createElement("div");
1204
1389
  row.className = "dsh-skin-telemetry-row";
1205
1390
  const metric = document.createElement("span");
@@ -1209,8 +1394,10 @@ body.dsh-skin-galactic-opera .dsh-skin-telemetry-value-full {
1209
1394
  return row;
1210
1395
  }));
1211
1396
  };
1397
+ const isTelemetryPaused = () => document.activeElement instanceof Element && isInstructionInputTarget(document.activeElement);
1212
1398
  const update = () => {
1213
1399
  frame = 0;
1400
+ if (isTelemetryPaused()) return;
1214
1401
  const nextSources = new Set(chooseTelemetryElements());
1215
1402
  const text = [...nextSources].map(getTelemetryText).filter(Boolean).join(" | ");
1216
1403
  for (const source of currentSources) if (!nextSources.has(source)) source.classList.remove("dsh-skin-telemetry-source-hidden");
@@ -1221,17 +1408,33 @@ body.dsh-skin-galactic-opera .dsh-skin-telemetry-value-full {
1221
1408
  renderPanel(text);
1222
1409
  };
1223
1410
  const schedule = () => {
1224
- if (frame === 0) frame = requestAnimationFrame(update);
1411
+ if (isTelemetryPaused()) return;
1412
+ if (frame === 0) frame = window.setTimeout(update, 180);
1413
+ };
1414
+ const onTelemetryFocusIn = (event) => {
1415
+ if (!isInstructionInputTarget(event.target)) return;
1416
+ if (frame !== 0) {
1417
+ window.clearTimeout(frame);
1418
+ frame = 0;
1419
+ }
1420
+ };
1421
+ const onTelemetryFocusOut = (event) => {
1422
+ if (isInstructionInputTarget(event.target)) window.setTimeout(schedule, 240);
1225
1423
  };
1226
1424
  const observer = typeof MutationObserver === "undefined" ? undefined : new MutationObserver(schedule);
1227
1425
  schedule();
1228
1426
  observer?.observe(document.body, { childList: true, subtree: true, characterData: true });
1229
1427
  window.addEventListener("resize", schedule, { passive: true });
1428
+ document.addEventListener("focusin", onTelemetryFocusIn);
1429
+ document.addEventListener("focusout", onTelemetryFocusOut);
1230
1430
  return () => {
1231
1431
  observer?.disconnect();
1232
1432
  window.removeEventListener("resize", schedule);
1233
- if (frame !== 0) cancelAnimationFrame(frame);
1433
+ document.removeEventListener("focusin", onTelemetryFocusIn);
1434
+ document.removeEventListener("focusout", onTelemetryFocusOut);
1435
+ if (frame !== 0) window.clearTimeout(frame);
1234
1436
  for (const source of currentSources) source.classList.remove("dsh-skin-telemetry-source-hidden");
1437
+ toggle.remove();
1235
1438
  panel.remove();
1236
1439
  };
1237
1440
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-skin-galactic-opera",
3
- "version": "0.1.2",
3
+ "version": "0.1.4",
4
4
  "description": "Unofficial cinematic space-opera dark skin bundle for the DSH Web GUI.",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",