@oh-my-pi/pi-tui 18.4.11 → 18.4.12

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,12 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [18.4.12] - 2026-10-02
6
+
7
+ ### Changed
8
+
9
+ - Changed Ctrl+Z in Tern's native composer to undo the last edit (TSP `undo` event) instead of suspending
10
+
5
11
  ## [18.4.11] - 2026-10-02
6
12
 
7
13
  ### Added
@@ -296,7 +296,7 @@ export declare class Editor implements Component, Focusable {
296
296
  submit(): void;
297
297
  /** Insert text at the current cursor position */
298
298
  insertText(text: string): void;
299
- /** Terminal-side selection edits on the `editor` node (see {@link applyHostEdit}). */
299
+ /** Terminal-side selection edits and undo on the `editor` node (see {@link applyHostEdit}). */
300
300
  handleNativeEvent(event: NativeUiEvent): void;
301
301
  /**
302
302
  * Apply an edit the terminal made over its own selection (TSP `edit`):
@@ -39,7 +39,7 @@ export declare class Input implements Component, Focusable {
39
39
  /** Apply terminal paste semantics to text from non-bracketed paste transports
40
40
  * (e.g. kitty's OSC 5522 enhanced clipboard read). Mirrors `Editor.pasteText`. */
41
41
  pasteText(text: string): void;
42
- /** Terminal-side selection edits on the `input` node (see {@link applyHostEdit}). */
42
+ /** Terminal-side selection edits and undo on the `input` node (see {@link applyHostEdit}). */
43
43
  handleNativeEvent(event: NativeUiEvent): void;
44
44
  /**
45
45
  * Apply an edit the terminal made over its own selection (TSP `edit`):
@@ -27,7 +27,8 @@ export declare function encodeTspJson(verb: TspVerb, value: unknown, params?: Ts
27
27
  /**
28
28
  * The `hello` query; callers follow it with a DA1 sentinel. `features: ["edit"]`
29
29
  * tells the terminal that omp applies its `edit` events (TSP §8.5), so it may keep a
30
- * native selection in omp's editors; without it, every key stays omp's.
30
+ * native selection in omp's editors; without it, every key stays omp's. `"undo"`
31
+ * says omp applies `undo` events, so the terminal may turn ⌃Z in a field into one.
31
32
  */
32
33
  export declare function encodeTspHelloQuery(version?: string): string;
33
34
  /** One decoded APC message: verb, parameters and raw body. */
@@ -117,7 +117,12 @@ export type NativeUiEvent = {
117
117
  | ({
118
118
  readonly type: "edit";
119
119
  readonly key: string;
120
- } & NativeTextEdit);
120
+ } & NativeTextEdit)
121
+ /** Undo the last change to an `editor`/`input` node's text (the terminal's ⌃Z); a no-op with no history. */
122
+ | {
123
+ readonly type: "undo";
124
+ readonly key: string;
125
+ };
121
126
  /**
122
127
  * A primitive edit the terminal made over its own text selection (cut,
123
128
  * typing, Backspace/Delete or paste over it, or collapsing it). Offsets are
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "@oh-my-pi/pi-tui",
4
- "version": "18.4.11",
4
+ "version": "18.4.12",
5
5
  "description": "Terminal User Interface library with differential rendering for efficient text-based applications",
6
6
  "homepage": "https://omp.sh",
7
7
  "author": {
@@ -41,14 +41,14 @@
41
41
  "gen:glyphs": "bun scripts/gen-glyphs.ts"
42
42
  },
43
43
  "dependencies": {
44
- "@oh-my-pi/omptype": "18.4.11",
45
- "@oh-my-pi/pi-agent-core": "18.4.11",
46
- "@oh-my-pi/pi-ai": "18.4.11",
47
- "@oh-my-pi/pi-catalog": "18.4.11",
48
- "@oh-my-pi/pi-natives": "18.4.11",
49
- "@oh-my-pi/pi-utils": "18.4.11",
50
- "@oh-my-pi/pi-wire": "18.4.11",
51
- "@oh-my-pi/snapcompact": "18.4.11"
44
+ "@oh-my-pi/omptype": "18.4.12",
45
+ "@oh-my-pi/pi-agent-core": "18.4.12",
46
+ "@oh-my-pi/pi-ai": "18.4.12",
47
+ "@oh-my-pi/pi-catalog": "18.4.12",
48
+ "@oh-my-pi/pi-natives": "18.4.12",
49
+ "@oh-my-pi/pi-utils": "18.4.12",
50
+ "@oh-my-pi/pi-wire": "18.4.12",
51
+ "@oh-my-pi/snapcompact": "18.4.12"
52
52
  },
53
53
  "devDependencies": {
54
54
  "kitty-vt-wasm": "^0.2.0"
@@ -1007,7 +1007,7 @@ export class Sidebar {
1007
1007
  * text field being edited. False when not the sidebar's event.
1008
1008
  */
1009
1009
  handleNativeEvent(event: NativeUiEvent): boolean {
1010
- if (event.type === "edit") {
1010
+ if (event.type === "edit" || event.type === "undo") {
1011
1011
  const editing = this.editing ? this.selected?.kind : undefined;
1012
1012
  const field =
1013
1013
  editing === "summary"
@@ -1017,7 +1017,7 @@ export class Sidebar {
1017
1017
  : editing === "description"
1018
1018
  ? this.description
1019
1019
  : undefined;
1020
- field?.applyHostEdit(event);
1020
+ field?.handleNativeEvent(event);
1021
1021
  return field !== undefined;
1022
1022
  }
1023
1023
  if (event.type === "select" || event.type === "activate") {
@@ -2862,9 +2862,10 @@ export class Editor implements Component, Focusable {
2862
2862
  this.#insertTextAtCursor(text);
2863
2863
  }
2864
2864
 
2865
- /** Terminal-side selection edits on the `editor` node (see {@link applyHostEdit}). */
2865
+ /** Terminal-side selection edits and undo on the `editor` node (see {@link applyHostEdit}). */
2866
2866
  handleNativeEvent(event: NativeUiEvent): void {
2867
2867
  if (event.type === "edit") this.applyHostEdit(event);
2868
+ else if (event.type === "undo") this.#applyUndo();
2868
2869
  }
2869
2870
 
2870
2871
  /**
@@ -284,9 +284,10 @@ export class Input implements Component, Focusable {
284
284
  this.#handlePaste(text);
285
285
  }
286
286
 
287
- /** Terminal-side selection edits on the `input` node (see {@link applyHostEdit}). */
287
+ /** Terminal-side selection edits and undo on the `input` node (see {@link applyHostEdit}). */
288
288
  handleNativeEvent(event: NativeUiEvent): void {
289
289
  if (event.type === "edit") this.applyHostEdit(event);
290
+ else if (event.type === "undo") this.#undo();
290
291
  }
291
292
 
292
293
  /**
@@ -671,6 +671,7 @@ export class NativeBackend {
671
671
  case "action":
672
672
  case "change":
673
673
  case "edit":
674
+ case "undo":
674
675
  this.#routeUiEvent(event);
675
676
  return;
676
677
  case "focus": {
@@ -687,7 +688,7 @@ export class NativeBackend {
687
688
  }
688
689
 
689
690
  #routeUiEvent(
690
- event: Extract<TspEvent, { ev: "toggle" | "select" | "activate" | "action" | "change" | "edit" }>,
691
+ event: Extract<TspEvent, { ev: "toggle" | "select" | "activate" | "action" | "change" | "edit" | "undo" }>,
691
692
  ): void {
692
693
  const reconciler = this.#surfaceFor(event.sf)?.reconciler;
693
694
  const target = reconciler?.target(event.id);
@@ -721,6 +722,9 @@ export class NativeBackend {
721
722
  ui = { type: "edit", key: target.keypath, from, to, text, cursor, len };
722
723
  break;
723
724
  }
725
+ case "undo":
726
+ ui = { type: "undo", key: target.keypath };
727
+ break;
724
728
  }
725
729
  target.component.handleNativeEvent(ui);
726
730
  this.#host.requestRender();
@@ -109,10 +109,11 @@ export function encodeTspJson(verb: TspVerb, value: unknown, params?: TspParams,
109
109
  /**
110
110
  * The `hello` query; callers follow it with a DA1 sentinel. `features: ["edit"]`
111
111
  * tells the terminal that omp applies its `edit` events (TSP §8.5), so it may keep a
112
- * native selection in omp's editors; without it, every key stays omp's.
112
+ * native selection in omp's editors; without it, every key stays omp's. `"undo"`
113
+ * says omp applies `undo` events, so the terminal may turn ⌃Z in a field into one.
113
114
  */
114
115
  export function encodeTspHelloQuery(version?: string): string {
115
- return encodeTspJson("q", { q: "hello", v: [TSP_VERSION], app: "omp", features: ["edit"], ver: version });
116
+ return encodeTspJson("q", { q: "hello", v: [TSP_VERSION], app: "omp", features: ["edit", "undo"], ver: version });
116
117
  }
117
118
 
118
119
  /** One decoded APC message: verb, parameters and raw body. */
@@ -172,6 +173,7 @@ const EVENT_REQUIRED: Readonly<Record<string, Readonly<Record<string, "string" |
172
173
  // `value` varies by control (boolean, number, string, string[], null): the handler checks it.
173
174
  change: { id: "string", item: "string" },
174
175
  edit: { id: "string", from: "number", to: "number", text: "string", cursor: "number", len: "number" },
176
+ undo: { id: "string" },
175
177
  focus: { id: "string" },
176
178
  error: { msg: "string" },
177
179
  gone: { ids: "array" },
@@ -113,7 +113,9 @@ export type NativeUiEvent =
113
113
  readonly value: boolean | number | string | readonly string[] | null;
114
114
  }
115
115
  /** An edit over the terminal's own selection in an `editor`/`input` node (see {@link NativeTextEdit}). */
116
- | ({ readonly type: "edit"; readonly key: string } & NativeTextEdit);
116
+ | ({ readonly type: "edit"; readonly key: string } & NativeTextEdit)
117
+ /** Undo the last change to an `editor`/`input` node's text (the terminal's ⌃Z); a no-op with no history. */
118
+ | { readonly type: "undo"; readonly key: string };
117
119
 
118
120
  /**
119
121
  * A primitive edit the terminal made over its own text selection (cut,