@cascadetui/core 0.1.4 → 0.1.6

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/Renderable.d.ts CHANGED
@@ -173,6 +173,9 @@ export declare abstract class Renderable extends BaseRenderable {
173
173
  onSelectionChanged(selection: Selection | null): boolean;
174
174
  getSelectedText(): string;
175
175
  shouldStartSelection(x: number, y: number): boolean;
176
+ selectWord(_x: number, _y: number): boolean;
177
+ selectLine(_x: number, _y: number): boolean;
178
+ updateSelectionWordSnap(_x: number, _y: number): boolean;
176
179
  focus(): void;
177
180
  blur(): void;
178
181
  get focused(): boolean;
@@ -254,6 +257,7 @@ export declare abstract class Renderable extends BaseRenderable {
254
257
  */
255
258
  protected onResize(width: number, height: number): void;
256
259
  private replaceParent;
260
+ private assertCanAdoptChild;
257
261
  add(obj: Renderable | VNode<any, any[]> | unknown, index?: number): number;
258
262
  insertBefore(obj: Renderable | VNode<any, any[]> | unknown, anchor?: Renderable | unknown): number;
259
263
  getRenderable(id: string): Renderable | undefined;
@@ -6112,15 +6112,16 @@ class StdinBuffer extends EventEmitter2 {
6112
6112
  this.timeout = null;
6113
6113
  }
6114
6114
  let str;
6115
- if (Buffer.isBuffer(data)) {
6116
- if (data.length === 1 && data[0] > 127) {
6117
- const byte = data[0] - 128;
6115
+ if (typeof data === "string") {
6116
+ str = data;
6117
+ } else {
6118
+ const chunk = this.toBuffer(data);
6119
+ if (chunk.length === 1 && chunk[0] > 127) {
6120
+ const byte = chunk[0] - 128;
6118
6121
  str = "\x1B" + String.fromCharCode(byte);
6119
6122
  } else {
6120
- str = data.toString();
6123
+ str = chunk.toString();
6121
6124
  }
6122
- } else {
6123
- str = data;
6124
6125
  }
6125
6126
  if (str.length === 0 && this.buffer.length === 0) {
6126
6127
  this.emit("data", "");
@@ -6210,6 +6211,15 @@ class StdinBuffer extends EventEmitter2 {
6210
6211
  destroy() {
6211
6212
  this.clear();
6212
6213
  }
6214
+ toBuffer(data) {
6215
+ if (Buffer.isBuffer(data)) {
6216
+ return data;
6217
+ }
6218
+ if (data instanceof Uint8Array) {
6219
+ return Buffer.from(data.buffer, data.byteOffset, data.byteLength);
6220
+ }
6221
+ return Buffer.from(data);
6222
+ }
6213
6223
  }
6214
6224
 
6215
6225
  // src/lib/yoga.options.ts
@@ -6515,7 +6525,16 @@ class MouseParser {
6515
6525
  this.mouseButtonsPressed.clear();
6516
6526
  }
6517
6527
  decodeInput(data) {
6518
- return data.toString();
6528
+ if (typeof data === "string") {
6529
+ return data;
6530
+ }
6531
+ if (Buffer.isBuffer(data)) {
6532
+ return data.toString();
6533
+ }
6534
+ if (data instanceof Uint8Array) {
6535
+ return Buffer.from(data.buffer, data.byteOffset, data.byteLength).toString();
6536
+ }
6537
+ return Buffer.from(data).toString();
6519
6538
  }
6520
6539
  parseMouseEvent(data) {
6521
6540
  const str = this.decodeInput(data);
@@ -13449,6 +13468,15 @@ class Renderable extends BaseRenderable {
13449
13468
  shouldStartSelection(x, y) {
13450
13469
  return false;
13451
13470
  }
13471
+ selectWord(_x, _y) {
13472
+ return false;
13473
+ }
13474
+ selectLine(_x, _y) {
13475
+ return false;
13476
+ }
13477
+ updateSelectionWordSnap(_x, _y) {
13478
+ return false;
13479
+ }
13452
13480
  focus() {
13453
13481
  if (this._isDestroyed || this._focused || !this._focusable)
13454
13482
  return;
@@ -13517,13 +13545,23 @@ class Renderable extends BaseRenderable {
13517
13545
  this.parent?.propagateLiveCount(delta);
13518
13546
  }
13519
13547
  findDescendantById(id) {
13520
- for (const child of this._childrenInLayoutOrder) {
13521
- if (child.id === id)
13522
- return child;
13523
- if (isRenderable(child)) {
13524
- const found = child.findDescendantById(id);
13525
- if (found)
13526
- return found;
13548
+ const visited = new Set;
13549
+ const stack = [...this._childrenInLayoutOrder];
13550
+ while (stack.length > 0) {
13551
+ const current = stack.pop();
13552
+ if (visited.has(current)) {
13553
+ continue;
13554
+ }
13555
+ visited.add(current);
13556
+ if (current.id === id) {
13557
+ return current;
13558
+ }
13559
+ const children = current.getChildren();
13560
+ for (let i = children.length - 1;i >= 0; i -= 1) {
13561
+ const child = children[i];
13562
+ if (isRenderable(child)) {
13563
+ stack.push(child);
13564
+ }
13527
13565
  }
13528
13566
  }
13529
13567
  return;
@@ -14046,6 +14084,23 @@ class Renderable extends BaseRenderable {
14046
14084
  }
14047
14085
  obj.parent = this;
14048
14086
  }
14087
+ assertCanAdoptChild(renderable) {
14088
+ if (renderable === this) {
14089
+ throw new Error(`Invalid render tree operation: '${this.id}' cannot contain itself`);
14090
+ }
14091
+ let current = this;
14092
+ const visited = new Set;
14093
+ while (current) {
14094
+ if (visited.has(current)) {
14095
+ throw new Error(`Invalid render tree operation: parent chain cycle detected near '${current.id}'`);
14096
+ }
14097
+ visited.add(current);
14098
+ if (current === renderable) {
14099
+ throw new Error(`Invalid render tree operation: adding '${renderable.id}' to '${this.id}' would create a cycle`);
14100
+ }
14101
+ current = current.parent;
14102
+ }
14103
+ }
14049
14104
  add(obj, index) {
14050
14105
  if (!obj) {
14051
14106
  return -1;
@@ -14060,6 +14115,7 @@ class Renderable extends BaseRenderable {
14060
14115
  }
14061
14116
  return -1;
14062
14117
  }
14118
+ this.assertCanAdoptChild(renderable);
14063
14119
  const anchorRenderable = index !== undefined ? this._childrenInLayoutOrder[index] : undefined;
14064
14120
  if (anchorRenderable) {
14065
14121
  return this.insertBefore(renderable, anchorRenderable);
@@ -14105,6 +14161,7 @@ class Renderable extends BaseRenderable {
14105
14161
  }
14106
14162
  return -1;
14107
14163
  }
14164
+ this.assertCanAdoptChild(renderable);
14108
14165
  if (!isRenderable(anchor)) {
14109
14166
  throw new Error("Anchor must be a Renderable");
14110
14167
  }
@@ -14308,6 +14365,9 @@ class Renderable extends BaseRenderable {
14308
14365
  }
14309
14366
  destroySelf() {}
14310
14367
  processMouseEvent(event) {
14368
+ if (!event.tryVisit(this)) {
14369
+ return;
14370
+ }
14311
14371
  this._mouseListener?.call(this, event);
14312
14372
  this._mouseListeners[event.type]?.call(this, event);
14313
14373
  this.onMouseEvent(event);
@@ -16024,6 +16084,12 @@ registerEnvVar({
16024
16084
  type: "boolean",
16025
16085
  default: false
16026
16086
  });
16087
+ registerEnvVar({
16088
+ name: "CASCADE_LOG_CRASH_REPORTS",
16089
+ description: "Log detailed crash reports to the console when a crash is captured.",
16090
+ type: "boolean",
16091
+ default: false
16092
+ });
16027
16093
  var DEFAULT_FORWARDED_ENV_KEYS = [
16028
16094
  "TMUX",
16029
16095
  "TERM",
@@ -16080,8 +16146,10 @@ class MouseEvent {
16080
16146
  scroll;
16081
16147
  target;
16082
16148
  isDragging;
16149
+ clickCount;
16083
16150
  _propagationStopped = false;
16084
16151
  _defaultPrevented = false;
16152
+ _visitedRenderableNums = new Set;
16085
16153
  get propagationStopped() {
16086
16154
  return this._propagationStopped;
16087
16155
  }
@@ -16098,6 +16166,7 @@ class MouseEvent {
16098
16166
  this.scroll = attributes.scroll;
16099
16167
  this.source = attributes.source;
16100
16168
  this.isDragging = attributes.isDragging;
16169
+ this.clickCount = attributes.clickCount ?? 1;
16101
16170
  }
16102
16171
  stopPropagation() {
16103
16172
  this._propagationStopped = true;
@@ -16105,6 +16174,13 @@ class MouseEvent {
16105
16174
  preventDefault() {
16106
16175
  this._defaultPrevented = true;
16107
16176
  }
16177
+ tryVisit(renderable) {
16178
+ if (this._visitedRenderableNums.has(renderable.num)) {
16179
+ return false;
16180
+ }
16181
+ this._visitedRenderableNums.add(renderable.num);
16182
+ return true;
16183
+ }
16108
16184
  }
16109
16185
  var MouseButton;
16110
16186
  ((MouseButton2) => {
@@ -16169,6 +16245,7 @@ var CliRenderEvents;
16169
16245
  ((CliRenderEvents2) => {
16170
16246
  CliRenderEvents2["DEBUG_OVERLAY_TOGGLE"] = "debugOverlay:toggle";
16171
16247
  CliRenderEvents2["DESTROY"] = "destroy";
16248
+ CliRenderEvents2["CRASH"] = "crash";
16172
16249
  })(CliRenderEvents ||= {});
16173
16250
  var RendererControlState;
16174
16251
  ((RendererControlState2) => {
@@ -16282,9 +16359,12 @@ class CliRenderer extends EventEmitter9 {
16282
16359
  _hasPointer = false;
16283
16360
  _lastPointerModifiers = { shift: false, alt: false, ctrl: false };
16284
16361
  _currentMousePointerStyle = undefined;
16362
+ _lastClick = null;
16363
+ clickCountThresholdMs = 400;
16285
16364
  _currentFocusedRenderable = null;
16286
16365
  lifecyclePasses = new Set;
16287
16366
  _openConsoleOnError = true;
16367
+ _logCrashReportsToConsole = env.CASCADE_LOG_CRASH_REPORTS;
16288
16368
  _paletteDetector = null;
16289
16369
  _cachedPalette = null;
16290
16370
  _paletteDetectionPromise = null;
@@ -16295,11 +16375,23 @@ class CliRenderer extends EventEmitter9 {
16295
16375
  idleResolvers = [];
16296
16376
  _debugInputs = [];
16297
16377
  _debugModeEnabled = env.CASCADE_DEBUG;
16298
- handleError = ((error) => {
16299
- console.error(error);
16378
+ recentRuntimeEvents = [];
16379
+ crashReports = [];
16380
+ maxRecentRuntimeEvents = 200;
16381
+ maxCrashReports = 20;
16382
+ handleProcessCrash = (reason, source) => {
16383
+ const report = this.reportCrash(reason, source);
16384
+ console.error(reason);
16300
16385
  if (this._openConsoleOnError) {
16301
16386
  this.console.show();
16387
+ console.log(`[crash:${report.source}] ${report.message}`);
16302
16388
  }
16389
+ };
16390
+ uncaughtExceptionHandler = ((error) => {
16391
+ this.handleProcessCrash(error, "uncaughtException");
16392
+ }).bind(this);
16393
+ unhandledRejectionHandler = ((reason) => {
16394
+ this.handleProcessCrash(reason, "unhandledRejection");
16303
16395
  }).bind(this);
16304
16396
  dumpOutputCache(optionalMessage = "") {
16305
16397
  const cachedLogs = this.console.getCachedLogs();
@@ -16401,8 +16493,8 @@ Captured output:
16401
16493
  }
16402
16494
  process.on("SIGWINCH", this.sigwinchHandler);
16403
16495
  process.on("warning", this.warningHandler);
16404
- process.on("uncaughtException", this.handleError);
16405
- process.on("unhandledRejection", this.handleError);
16496
+ process.on("uncaughtException", this.uncaughtExceptionHandler);
16497
+ process.on("unhandledRejection", this.unhandledRejectionHandler);
16406
16498
  process.on("beforeExit", this.exitHandler);
16407
16499
  const kittyConfig = config.useKittyKeyboard ?? {};
16408
16500
  const useKittyForParsing = kittyConfig !== null;
@@ -16432,6 +16524,7 @@ Captured output:
16432
16524
  this._console = new TerminalConsole(this, consoleOptions);
16433
16525
  this.useConsole = config.useConsole ?? true;
16434
16526
  this._openConsoleOnError = config.openConsoleOnError ?? true;
16527
+ this._logCrashReportsToConsole = config.logCrashReportsToConsole ?? env.CASCADE_LOG_CRASH_REPORTS;
16435
16528
  this._onDestroy = config.onDestroy;
16436
16529
  global.requestAnimationFrame = (callback) => {
16437
16530
  const id = CliRenderer.animationFrameId++;
@@ -16773,10 +16866,11 @@ Captured output:
16773
16866
  this.queryPixelResolution();
16774
16867
  }
16775
16868
  stdinListener = ((data) => {
16776
- if (this._useMouse && this.handleMouseData(data)) {
16869
+ const chunk = this.normalizeInputChunk(data);
16870
+ if (this._useMouse && this.handleMouseData(chunk)) {
16777
16871
  return;
16778
16872
  }
16779
- this._stdinBuffer.process(data);
16873
+ this._stdinBuffer.process(chunk);
16780
16874
  }).bind(this);
16781
16875
  addInputHandler(handler) {
16782
16876
  this.inputHandlers.push(handler);
@@ -16853,6 +16947,10 @@ Captured output:
16853
16947
  this.stdin.setEncoding("utf8");
16854
16948
  this.stdin.on("data", this.stdinListener);
16855
16949
  this._stdinBuffer.on("data", (sequence) => {
16950
+ this.recordRuntimeEvent("input:data", {
16951
+ sequence: sequence.length > 120 ? `${sequence.slice(0, 120)}...` : sequence,
16952
+ length: sequence.length
16953
+ });
16856
16954
  if (this._debugModeEnabled) {
16857
16955
  this._debugInputs.push({
16858
16956
  timestamp: new Date().toISOString(),
@@ -16866,6 +16964,9 @@ Captured output:
16866
16964
  }
16867
16965
  });
16868
16966
  this._stdinBuffer.on("paste", (data) => {
16967
+ this.recordRuntimeEvent("input:paste", {
16968
+ length: data.length
16969
+ });
16869
16970
  this._keyHandler.processPaste(data);
16870
16971
  });
16871
16972
  }
@@ -16874,7 +16975,12 @@ Captured output:
16874
16975
  target.processMouseEvent(event);
16875
16976
  if (this.autoFocus && event.type === "down" && event.button === 0 /* LEFT */ && !event.defaultPrevented) {
16876
16977
  let current = target;
16978
+ const visited = new Set;
16877
16979
  while (current) {
16980
+ if (visited.has(current)) {
16981
+ break;
16982
+ }
16983
+ visited.add(current);
16878
16984
  if (current.focusable) {
16879
16985
  current.focus();
16880
16986
  break;
@@ -16903,6 +17009,18 @@ Captured output:
16903
17009
  }
16904
17010
  mouseEvent.y -= this.renderOffset;
16905
17011
  }
17012
+ const clickCount = this.resolveClickCount(mouseEvent);
17013
+ const mouseEventWithClickCount = { ...mouseEvent, clickCount };
17014
+ this.recordRuntimeEvent("input:mouse", {
17015
+ type: mouseEvent.type,
17016
+ x: mouseEvent.x,
17017
+ y: mouseEvent.y,
17018
+ button: mouseEvent.button,
17019
+ clickCount,
17020
+ ctrl: mouseEvent.modifiers.ctrl,
17021
+ alt: mouseEvent.modifiers.alt,
17022
+ shift: mouseEvent.modifiers.shift
17023
+ });
16906
17024
  this._latestPointer.x = mouseEvent.x;
16907
17025
  this._latestPointer.y = mouseEvent.y;
16908
17026
  this._hasPointer = true;
@@ -16910,7 +17028,7 @@ Captured output:
16910
17028
  if (this._console.visible) {
16911
17029
  const consoleBounds = this._console.bounds;
16912
17030
  if (mouseEvent.x >= consoleBounds.x && mouseEvent.x < consoleBounds.x + consoleBounds.width && mouseEvent.y >= consoleBounds.y && mouseEvent.y < consoleBounds.y + consoleBounds.height) {
16913
- const event2 = new MouseEvent(null, mouseEvent);
17031
+ const event2 = new MouseEvent(null, mouseEventWithClickCount);
16914
17032
  const handled = this._console.handleMouse(event2);
16915
17033
  if (handled)
16916
17034
  return true;
@@ -16922,7 +17040,7 @@ Captured output:
16922
17040
  const fallbackTarget = this._currentFocusedRenderable && !this._currentFocusedRenderable.isDestroyed && this._currentFocusedRenderable.focused ? this._currentFocusedRenderable : null;
16923
17041
  const scrollTarget = maybeRenderable2 ?? fallbackTarget;
16924
17042
  if (scrollTarget) {
16925
- const event2 = new MouseEvent(scrollTarget, mouseEvent);
17043
+ const event2 = new MouseEvent(scrollTarget, mouseEventWithClickCount);
16926
17044
  scrollTarget.processMouseEvent(event2);
16927
17045
  }
16928
17046
  return true;
@@ -16935,21 +17053,21 @@ Captured output:
16935
17053
  const canStartSelection = Boolean(maybeRenderable && maybeRenderable.selectable && !maybeRenderable.isDestroyed && maybeRenderable.shouldStartSelection(mouseEvent.x, mouseEvent.y));
16936
17054
  if (canStartSelection && maybeRenderable) {
16937
17055
  this.startSelection(maybeRenderable, mouseEvent.x, mouseEvent.y);
16938
- this.dispatchMouseEvent(maybeRenderable, mouseEvent);
17056
+ this.dispatchMouseEvent(maybeRenderable, mouseEventWithClickCount);
16939
17057
  return true;
16940
17058
  }
16941
17059
  }
16942
17060
  if (mouseEvent.type === "drag" && this.currentSelection?.isDragging) {
16943
17061
  this.updateSelection(maybeRenderable, mouseEvent.x, mouseEvent.y);
16944
17062
  if (maybeRenderable) {
16945
- const event2 = new MouseEvent(maybeRenderable, { ...mouseEvent, isDragging: true });
17063
+ const event2 = new MouseEvent(maybeRenderable, { ...mouseEventWithClickCount, isDragging: true });
16946
17064
  maybeRenderable.processMouseEvent(event2);
16947
17065
  }
16948
17066
  return true;
16949
17067
  }
16950
17068
  if (mouseEvent.type === "up" && this.currentSelection?.isDragging) {
16951
17069
  if (maybeRenderable) {
16952
- const event2 = new MouseEvent(maybeRenderable, { ...mouseEvent, isDragging: true });
17070
+ const event2 = new MouseEvent(maybeRenderable, { ...mouseEventWithClickCount, isDragging: true });
16953
17071
  maybeRenderable.processMouseEvent(event2);
16954
17072
  }
16955
17073
  this.finishSelection();
@@ -16964,13 +17082,13 @@ Captured output:
16964
17082
  }
16965
17083
  if (!sameElement && (mouseEvent.type === "drag" || mouseEvent.type === "move")) {
16966
17084
  if (this.lastOverRenderable && this.lastOverRenderable !== this.capturedRenderable) {
16967
- const event2 = new MouseEvent(this.lastOverRenderable, { ...mouseEvent, type: "out" });
17085
+ const event2 = new MouseEvent(this.lastOverRenderable, { ...mouseEventWithClickCount, type: "out" });
16968
17086
  this.lastOverRenderable.processMouseEvent(event2);
16969
17087
  }
16970
17088
  this.lastOverRenderable = maybeRenderable;
16971
17089
  if (maybeRenderable) {
16972
17090
  const event2 = new MouseEvent(maybeRenderable, {
16973
- ...mouseEvent,
17091
+ ...mouseEventWithClickCount,
16974
17092
  type: "over",
16975
17093
  source: this.capturedRenderable
16976
17094
  });
@@ -16978,17 +17096,17 @@ Captured output:
16978
17096
  }
16979
17097
  }
16980
17098
  if (this.capturedRenderable && mouseEvent.type !== "up") {
16981
- const event2 = new MouseEvent(this.capturedRenderable, mouseEvent);
17099
+ const event2 = new MouseEvent(this.capturedRenderable, mouseEventWithClickCount);
16982
17100
  this.capturedRenderable.processMouseEvent(event2);
16983
17101
  return true;
16984
17102
  }
16985
17103
  if (this.capturedRenderable && mouseEvent.type === "up") {
16986
- const event2 = new MouseEvent(this.capturedRenderable, { ...mouseEvent, type: "drag-end" });
17104
+ const event2 = new MouseEvent(this.capturedRenderable, { ...mouseEventWithClickCount, type: "drag-end" });
16987
17105
  this.capturedRenderable.processMouseEvent(event2);
16988
- this.capturedRenderable.processMouseEvent(new MouseEvent(this.capturedRenderable, mouseEvent));
17106
+ this.capturedRenderable.processMouseEvent(new MouseEvent(this.capturedRenderable, mouseEventWithClickCount));
16989
17107
  if (maybeRenderable) {
16990
17108
  const event3 = new MouseEvent(maybeRenderable, {
16991
- ...mouseEvent,
17109
+ ...mouseEventWithClickCount,
16992
17110
  type: "drop",
16993
17111
  source: this.capturedRenderable
16994
17112
  });
@@ -17006,7 +17124,7 @@ Captured output:
17006
17124
  } else {
17007
17125
  this.setCapturedRenderable(undefined);
17008
17126
  }
17009
- event = this.dispatchMouseEvent(maybeRenderable, mouseEvent);
17127
+ event = this.dispatchMouseEvent(maybeRenderable, mouseEventWithClickCount);
17010
17128
  } else {
17011
17129
  this.setCapturedRenderable(undefined);
17012
17130
  this.lastOverRenderable = undefined;
@@ -17176,6 +17294,115 @@ Captured output:
17176
17294
  copyToClipboardOSC52(text, target) {
17177
17295
  return this.clipboard.copyToClipboardOSC52(text, target);
17178
17296
  }
17297
+ normalizeInputChunk(data) {
17298
+ if (typeof data === "string") {
17299
+ return data;
17300
+ }
17301
+ if (Buffer.isBuffer(data)) {
17302
+ return data;
17303
+ }
17304
+ if (data instanceof Uint8Array) {
17305
+ return Buffer.from(data.buffer, data.byteOffset, data.byteLength);
17306
+ }
17307
+ return Buffer.from(data);
17308
+ }
17309
+ resolveClickCount(mouseEvent) {
17310
+ if (mouseEvent.type !== "down" || mouseEvent.button > 2 /* RIGHT */) {
17311
+ return 1;
17312
+ }
17313
+ const now = Date.now();
17314
+ const previous = this._lastClick;
17315
+ const isConsecutive = previous && previous.button === mouseEvent.button && previous.x === mouseEvent.x && previous.y === mouseEvent.y && now - previous.timestamp <= this.clickCountThresholdMs;
17316
+ const count = isConsecutive ? previous.count + 1 : 1;
17317
+ this._lastClick = {
17318
+ x: mouseEvent.x,
17319
+ y: mouseEvent.y,
17320
+ button: mouseEvent.button,
17321
+ timestamp: now,
17322
+ count
17323
+ };
17324
+ return count;
17325
+ }
17326
+ normalizeCrashError(reason) {
17327
+ if (reason instanceof Error) {
17328
+ return {
17329
+ message: reason.message || reason.name || "Unknown error",
17330
+ stack: reason.stack
17331
+ };
17332
+ }
17333
+ if (typeof reason === "string") {
17334
+ return { message: reason };
17335
+ }
17336
+ try {
17337
+ return { message: JSON.stringify(reason) };
17338
+ } catch {
17339
+ return { message: String(reason) };
17340
+ }
17341
+ }
17342
+ recordRuntimeEvent(type, payload) {
17343
+ this.recentRuntimeEvents.push({
17344
+ timestamp: new Date().toISOString(),
17345
+ type,
17346
+ payload
17347
+ });
17348
+ if (this.recentRuntimeEvents.length > this.maxRecentRuntimeEvents) {
17349
+ this.recentRuntimeEvents.shift();
17350
+ }
17351
+ }
17352
+ reportCrash(reason, source = "manual", extra) {
17353
+ const error = this.normalizeCrashError(reason);
17354
+ const report = {
17355
+ timestamp: new Date().toISOString(),
17356
+ source,
17357
+ message: error.message,
17358
+ stack: error.stack,
17359
+ recentEvents: [...this.recentRuntimeEvents]
17360
+ };
17361
+ if (extra && Object.keys(extra).length > 0) {
17362
+ report.recentEvents.push({
17363
+ timestamp: report.timestamp,
17364
+ type: "crash:context",
17365
+ payload: extra
17366
+ });
17367
+ }
17368
+ this.crashReports.push(report);
17369
+ if (this.crashReports.length > this.maxCrashReports) {
17370
+ this.crashReports.shift();
17371
+ }
17372
+ if (this._logCrashReportsToConsole) {
17373
+ console.error(this.formatCrashReportForConsole(report));
17374
+ }
17375
+ this.emit("crash" /* CRASH */, report);
17376
+ return report;
17377
+ }
17378
+ formatCrashReportForConsole(report) {
17379
+ const lines = [];
17380
+ lines.push("[Cascade Crash Report]");
17381
+ lines.push(`timestamp=${report.timestamp}`);
17382
+ lines.push(`source=${report.source}`);
17383
+ lines.push(`message=${report.message}`);
17384
+ if (report.stack) {
17385
+ lines.push("stack:");
17386
+ lines.push(report.stack);
17387
+ }
17388
+ if (report.recentEvents.length > 0) {
17389
+ lines.push(`recentEvents(${report.recentEvents.length}):`);
17390
+ for (const entry of report.recentEvents) {
17391
+ lines.push(`${entry.timestamp} ${entry.type} ${JSON.stringify(entry.payload)}`);
17392
+ }
17393
+ }
17394
+ return lines.join(`
17395
+ `);
17396
+ }
17397
+ getCrashReports() {
17398
+ return [...this.crashReports];
17399
+ }
17400
+ getRecentRuntimeEvents() {
17401
+ return [...this.recentRuntimeEvents];
17402
+ }
17403
+ clearCrashReports() {
17404
+ this.crashReports = [];
17405
+ }
17179
17406
  copyToSystemClipboard(text) {
17180
17407
  return this.clipboard.copyToSystemClipboard(text);
17181
17408
  }
@@ -17379,8 +17606,8 @@ Captured output:
17379
17606
  this._destroyFinalized = true;
17380
17607
  this._destroyPending = false;
17381
17608
  process.removeListener("SIGWINCH", this.sigwinchHandler);
17382
- process.removeListener("uncaughtException", this.handleError);
17383
- process.removeListener("unhandledRejection", this.handleError);
17609
+ process.removeListener("uncaughtException", this.uncaughtExceptionHandler);
17610
+ process.removeListener("unhandledRejection", this.unhandledRejectionHandler);
17384
17611
  process.removeListener("warning", this.warningHandler);
17385
17612
  process.removeListener("beforeExit", this.exitHandler);
17386
17613
  capture.removeListener("write", this.captureCallback);
@@ -17482,6 +17709,7 @@ Captured output:
17482
17709
  try {
17483
17710
  await frameCallback(deltaTime);
17484
17711
  } catch (error) {
17712
+ this.reportCrash(error, "frame-callback");
17485
17713
  console.error("Error in frame callback:", error);
17486
17714
  }
17487
17715
  }
@@ -17515,6 +17743,9 @@ Captured output:
17515
17743
  this.renderTimeout = null;
17516
17744
  }
17517
17745
  }
17746
+ } catch (error) {
17747
+ this.reportCrash(error, "render-loop");
17748
+ console.error("Error in render loop:", error);
17518
17749
  } finally {
17519
17750
  this.rendering = false;
17520
17751
  if (this._destroyPending) {
@@ -17591,6 +17822,30 @@ Captured output:
17591
17822
  }
17592
17823
  this.selectionContainers = [];
17593
17824
  }
17825
+ selectWord(x, y) {
17826
+ let current = this.resolveSelectionMethodTarget(x, y);
17827
+ while (current) {
17828
+ if (current.selectWord(x, y))
17829
+ return;
17830
+ current = current.parent;
17831
+ }
17832
+ }
17833
+ selectLine(x, y) {
17834
+ let current = this.resolveSelectionMethodTarget(x, y);
17835
+ while (current) {
17836
+ if (current.selectLine(x, y))
17837
+ return;
17838
+ current = current.parent;
17839
+ }
17840
+ }
17841
+ updateSelectionWordSnap(x, y) {
17842
+ let current = this.resolveSelectionMethodTarget(x, y);
17843
+ while (current) {
17844
+ if (current.updateSelectionWordSnap(x, y))
17845
+ return;
17846
+ current = current.parent;
17847
+ }
17848
+ }
17594
17849
  startSelection(renderable, x, y) {
17595
17850
  if (!renderable.selectable)
17596
17851
  return;
@@ -17636,7 +17891,11 @@ Captured output:
17636
17891
  }
17637
17892
  isWithinContainer(renderable, container) {
17638
17893
  let current = renderable;
17894
+ const visited = new Set;
17639
17895
  while (current) {
17896
+ if (visited.has(current))
17897
+ return false;
17898
+ visited.add(current);
17640
17899
  if (current === container)
17641
17900
  return true;
17642
17901
  current = current.parent;
@@ -17650,6 +17909,24 @@ Captured output:
17650
17909
  this.notifySelectablesOfSelectionChange();
17651
17910
  }
17652
17911
  }
17912
+ resolveSelectionMethodTarget(x, y) {
17913
+ const maybeRenderableId = this.hitTest(x, y);
17914
+ let current = Renderable.renderablesByNumber.get(maybeRenderableId) ?? null;
17915
+ while (current) {
17916
+ if (current.selectable && !current.isDestroyed) {
17917
+ return current;
17918
+ }
17919
+ current = current.parent;
17920
+ }
17921
+ const candidates = [...Renderable.renderablesByNumber.values()];
17922
+ for (let i = candidates.length - 1;i >= 0; i -= 1) {
17923
+ const candidate = candidates[i];
17924
+ if (candidate.selectable && !candidate.isDestroyed && x >= candidate.x && x < candidate.x + candidate.width && y >= candidate.y && y < candidate.y + candidate.height) {
17925
+ return candidate;
17926
+ }
17927
+ }
17928
+ return null;
17929
+ }
17653
17930
  notifySelectablesOfSelectionChange() {
17654
17931
  const selectedRenderables = [];
17655
17932
  const touchedRenderables = [];
@@ -17719,5 +17996,5 @@ Captured output:
17719
17996
 
17720
17997
  export { __toESM, __commonJS, __export, __require, Edge, Gutter, MeasureMode, exports_src, isValidBorderStyle, parseBorderStyle, BorderChars, getBorderFromSides, getBorderSides, borderCharsToArray, BorderCharArrays, nonAlphanumericKeys, parseKeypress, KeyEvent, PasteEvent, KeyHandler, InternalKeyHandler, RGBA, hexToRgb, rgbToHex, hsvToRgb, parseColor, fonts, measureText, getCharacterPositions, coordinateToCharacterIndex, renderFontToFrameBuffer, TextAttributes, ATTRIBUTE_BASE_BITS, ATTRIBUTE_BASE_MASK, getBaseAttributes, DebugOverlayCorner, createTextAttributes, attributesWithLink, getLinkId, visualizeRenderableTree, isStyledText, StyledText, stringToStyledText, black, red, green, yellow, blue, magenta, cyan, white, brightBlack, brightRed, brightGreen, brightYellow, brightBlue, brightMagenta, brightCyan, brightWhite, bgBlack, bgRed, bgGreen, bgYellow, bgBlue, bgMagenta, bgCyan, bgWhite, bold, italic, underline, strikethrough, dim, reverse, blink, fg, bg, link, t, hastToStyledText, LinearScrollAccel, MacOSScrollAccel, StdinBuffer, parseAlign, parseAlignItems, parseBoxSizing, parseDimension, parseDirection, parseDisplay, parseEdge, parseFlexDirection, parseGutter, parseJustify, parseLogLevel, parseMeasureMode, parseOverflow, parsePositionType, parseUnit, parseWrap, MouseParser, Selection, convertGlobalToLocalSelection, ASCIIFontSelectionHelper, envRegistry, registerEnvVar, clearEnvCache, generateEnvMarkdown, generateEnvColored, env, treeSitterToTextChunks, treeSitterToStyledText, addDefaultParsers, TreeSitterClient, DataPathsManager, getDataPaths, extToFiletype, pathToFiletype, main, getTreeSitterClient, ExtmarksController, createExtmarksController, TerminalPalette, createTerminalPalette, TextBuffer, SpanInfoStruct, LogLevel2 as LogLevel, setRenderLibPath, resolveRenderLib, OptimizedBuffer, h, isVNode, maybeMakeRenderable, wrapWithDelegates, instantiate, delegate, isValidPercentage, LayoutEvents, RenderableEvents, isRenderable, BaseRenderable, Renderable, RootRenderable, ANSI, defaultKeyAliases, mergeKeyAliases, mergeKeyBindings, getKeyBindingKey, buildKeyBindingsMap, capture, ConsolePosition, TerminalConsole, getObjectsInViewport, buildKittyKeyboardFlags, MouseEvent, MouseButton, createCliRenderer, CliRenderEvents, RendererControlState, CliRenderer };
17721
17998
 
17722
- //# debugId=0377C87661B220C664756E2164756E21
17723
- //# sourceMappingURL=index-jx194wn1.js.map
17999
+ //# debugId=F994E7E6202035C864756E2164756E21
18000
+ //# sourceMappingURL=index-rj3f00a6.js.map