@qodalis/cli 2.5.0 → 2.5.1

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/public-api.mjs CHANGED
@@ -518,7 +518,7 @@ var CliKeyValueStore_TOKEN = createCliToken("cli-key-value-store");
518
518
  var SyntaxHighlighterRegistry_TOKEN = createCliToken("syntax-highlighter-registry");
519
519
 
520
520
  // src/lib/version.ts
521
- var LIBRARY_VERSION = "2.5.0";
521
+ var LIBRARY_VERSION = "2.5.1";
522
522
  var API_VERSION = 2;
523
523
  var ANONYMOUS = "\0anonymous";
524
524
  function aliasOwner(context2) {
@@ -23864,6 +23864,143 @@ function createCompletionProviders(deps) {
23864
23864
  return [...fromPlugins, ...builtIn];
23865
23865
  }
23866
23866
 
23867
+ // src/lib/engine/cli-touch-scroll.ts
23868
+ var SLOP_PX = 8;
23869
+ var MIN_FLING = 0.15;
23870
+ var FRICTION = 0.997;
23871
+ var VELOCITY_WINDOW_MS = 100;
23872
+ var KEYBOARD_HOLD_MS = 400;
23873
+ function enableTouchScroll(terminal, paused = () => false) {
23874
+ const element = terminal.element;
23875
+ if (!element) {
23876
+ return () => {
23877
+ };
23878
+ }
23879
+ let startY = 0;
23880
+ let lastY = 0;
23881
+ let scrolling = false;
23882
+ let carry = 0;
23883
+ let moves = [];
23884
+ let frame = 0;
23885
+ let holdTimer = 0;
23886
+ let holding = false;
23887
+ const textarea = terminal.textarea;
23888
+ const keyboardOpen = () => window.innerHeight < screen.height * 0.75;
23889
+ const holdKeyboard = () => {
23890
+ clearTimeout(holdTimer);
23891
+ if (holding || !textarea || textarea.hasAttribute("inputmode") || keyboardOpen()) {
23892
+ return;
23893
+ }
23894
+ holding = true;
23895
+ textarea.setAttribute("inputmode", "none");
23896
+ };
23897
+ const releaseKeyboard = () => {
23898
+ clearTimeout(holdTimer);
23899
+ if (holding) {
23900
+ holding = false;
23901
+ textarea?.removeAttribute("inputmode");
23902
+ }
23903
+ };
23904
+ const rowHeight = () => {
23905
+ const screen2 = element.querySelector(".xterm-screen");
23906
+ return (screen2?.clientHeight || element.clientHeight) / terminal.rows || 16;
23907
+ };
23908
+ const scrollBy = (pixels) => {
23909
+ carry += pixels;
23910
+ const height = rowHeight();
23911
+ const rows = Math.trunc(carry / height);
23912
+ if (rows === 0) {
23913
+ return true;
23914
+ }
23915
+ carry -= rows * height;
23916
+ const buffer = terminal.buffer.active;
23917
+ const before = buffer.viewportY;
23918
+ terminal.scrollLines(-rows);
23919
+ const moved = buffer.viewportY !== before;
23920
+ if (!moved) {
23921
+ carry = 0;
23922
+ }
23923
+ return moved;
23924
+ };
23925
+ const stopGlide = () => {
23926
+ cancelAnimationFrame(frame);
23927
+ frame = 0;
23928
+ };
23929
+ const glide = (velocity) => {
23930
+ let previous = performance.now();
23931
+ const step = (now) => {
23932
+ const elapsed = Math.min(now - previous, 50);
23933
+ previous = now;
23934
+ velocity *= Math.pow(FRICTION, elapsed);
23935
+ if (Math.abs(velocity) < 0.02 || !scrollBy(velocity * elapsed)) {
23936
+ frame = 0;
23937
+ return;
23938
+ }
23939
+ frame = requestAnimationFrame(step);
23940
+ };
23941
+ frame = requestAnimationFrame(step);
23942
+ };
23943
+ const onStart = (e) => {
23944
+ stopGlide();
23945
+ scrolling = false;
23946
+ if (e.touches.length !== 1 || paused()) {
23947
+ return;
23948
+ }
23949
+ holdKeyboard();
23950
+ startY = lastY = e.touches[0].clientY;
23951
+ carry = 0;
23952
+ moves = [{ y: startY, time: e.timeStamp }];
23953
+ };
23954
+ const onMove = (e) => {
23955
+ if (e.touches.length !== 1 || paused() || moves.length === 0) {
23956
+ return;
23957
+ }
23958
+ const y = e.touches[0].clientY;
23959
+ if (!scrolling && Math.abs(y - startY) < SLOP_PX) {
23960
+ return;
23961
+ }
23962
+ scrolling = true;
23963
+ e.preventDefault();
23964
+ scrollBy(y - lastY);
23965
+ lastY = y;
23966
+ moves.push({ y, time: e.timeStamp });
23967
+ while (moves.length > 2 && e.timeStamp - moves[0].time > VELOCITY_WINDOW_MS) {
23968
+ moves.shift();
23969
+ }
23970
+ };
23971
+ const onEnd = (e) => {
23972
+ if (!scrolling) {
23973
+ releaseKeyboard();
23974
+ moves = [];
23975
+ return;
23976
+ }
23977
+ e.preventDefault();
23978
+ scrolling = false;
23979
+ holdTimer = window.setTimeout(releaseKeyboard, KEYBOARD_HOLD_MS);
23980
+ const first = moves[0];
23981
+ const last = moves[moves.length - 1];
23982
+ moves = [];
23983
+ const elapsed = last.time - first.time;
23984
+ const velocity = elapsed > 0 && e.timeStamp - last.time < VELOCITY_WINDOW_MS ? (last.y - first.y) / elapsed : 0;
23985
+ if (Math.abs(velocity) >= MIN_FLING) {
23986
+ glide(velocity);
23987
+ }
23988
+ };
23989
+ const options = { passive: false, capture: true };
23990
+ element.addEventListener("touchstart", onStart, options);
23991
+ element.addEventListener("touchmove", onMove, options);
23992
+ element.addEventListener("touchend", onEnd, options);
23993
+ element.addEventListener("touchcancel", onEnd, options);
23994
+ return () => {
23995
+ stopGlide();
23996
+ releaseKeyboard();
23997
+ element.removeEventListener("touchstart", onStart, options);
23998
+ element.removeEventListener("touchmove", onMove, options);
23999
+ element.removeEventListener("touchend", onEnd, options);
24000
+ element.removeEventListener("touchcancel", onEnd, options);
24001
+ };
24002
+ }
24003
+
23867
24004
  // src/lib/engine/cli-engine.ts
23868
24005
  var CliEngine = class {
23869
24006
  constructor(container, options) {
@@ -23975,6 +24112,12 @@ var CliEngine = class {
23975
24112
  this.serializeAddon = setup.serializeAddon;
23976
24113
  this.dragDropService = setup.dragDropService;
23977
24114
  this.wheelListener = setup.wheelListener;
24115
+ if (this.options?.touchScroll !== false) {
24116
+ this.disposeTouchScroll = enableTouchScroll(
24117
+ this.terminal,
24118
+ () => !!this.executionContext?.contextProcessor
24119
+ );
24120
+ }
23978
24121
  this.handleResize();
23979
24122
  }
23980
24123
  /** 2. Service container, boot service, executor and execution context. */
@@ -24204,6 +24347,7 @@ var CliEngine = class {
24204
24347
  if (this.wheelListener) {
24205
24348
  this.container.removeEventListener("wheel", this.wheelListener);
24206
24349
  }
24350
+ this.disposeTouchScroll?.();
24207
24351
  this.resizeVersion = -1;
24208
24352
  this.resizeScheduled = false;
24209
24353
  this.resizeObserver?.disconnect();
@@ -25112,6 +25256,21 @@ var DARK_SCHEME_QUERY = "(prefers-color-scheme: dark)";
25112
25256
  function asEventTarget(node) {
25113
25257
  return node && typeof node.addEventListener === "function" ? node : null;
25114
25258
  }
25259
+ function canScrollWithin(target, root, dx, dy) {
25260
+ for (let el = target; el && el !== root; el = el.parentElement) {
25261
+ if (!(el instanceof HTMLElement)) continue;
25262
+ const style = getComputedStyle(el);
25263
+ const scrollsY = /auto|scroll/.test(style.overflowY) && el.scrollHeight > el.clientHeight;
25264
+ const scrollsX = /auto|scroll/.test(style.overflowX) && el.scrollWidth > el.clientWidth;
25265
+ if (dy !== 0 && scrollsY) {
25266
+ if (dy < 0 ? el.scrollTop > 0 : el.scrollTop + el.clientHeight < el.scrollHeight) return true;
25267
+ }
25268
+ if (dx !== 0 && scrollsX) {
25269
+ if (dx < 0 ? el.scrollLeft > 0 : el.scrollLeft + el.clientWidth < el.scrollWidth) return true;
25270
+ }
25271
+ }
25272
+ return false;
25273
+ }
25115
25274
  function followsSystem(input) {
25116
25275
  return input === "auto" || typeof input === "object" && input !== null && input.base === "auto";
25117
25276
  }
@@ -25193,6 +25352,16 @@ var CliPanelController = class {
25193
25352
  if (event.target !== first) return;
25194
25353
  this.syncThemeFromEngine(event.detail);
25195
25354
  };
25355
+ /**
25356
+ * A wheel over the panel chrome (header, icon strip, empty pane) would
25357
+ * scroll the page behind it; the terminals already keep their own wheel.
25358
+ */
25359
+ this.onPanelWheel = (event) => {
25360
+ const wheel = event;
25361
+ const root = this.rootElement;
25362
+ if (!root || canScrollWithin(wheel.target, root, wheel.deltaX, wheel.deltaY)) return;
25363
+ wheel.preventDefault();
25364
+ };
25196
25365
  this.onVisualViewportChange = () => {
25197
25366
  const fields = visualViewportFields();
25198
25367
  const s = this.snapshot;
@@ -25301,9 +25470,13 @@ var CliPanelController = class {
25301
25470
  /** Element containing the terminals, used for theme sync. */
25302
25471
  setRootElement(element) {
25303
25472
  if (element === this.rootElement) return;
25304
- asEventTarget(this.rootElement)?.removeEventListener(CLI_TERMINAL_THEME_EVENT, this.onTerminalTheme);
25473
+ const previous = asEventTarget(this.rootElement);
25474
+ previous?.removeEventListener(CLI_TERMINAL_THEME_EVENT, this.onTerminalTheme);
25475
+ previous?.removeEventListener("wheel", this.onPanelWheel);
25305
25476
  this.rootElement = element;
25306
- asEventTarget(element)?.addEventListener(CLI_TERMINAL_THEME_EVENT, this.onTerminalTheme);
25477
+ const next = asEventTarget(element);
25478
+ next?.addEventListener(CLI_TERMINAL_THEME_EVENT, this.onTerminalTheme);
25479
+ next?.addEventListener("wheel", this.onPanelWheel, { passive: false });
25307
25480
  if (element && this.followsTerminalTheme) this.startThemeSync();
25308
25481
  }
25309
25482
  /**