silvery 0.21.0 → 0.23.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 (224) hide show
  1. package/README.md +1 -1
  2. package/dist/{Text-Lq0dmj8-.mjs → Text-Ci6UCSTL.mjs} +46 -48
  3. package/dist/Text-Ci6UCSTL.mjs.map +1 -0
  4. package/dist/{render-string-DkQacASz.mjs → ag-q9lRlKlt.mjs} +5322 -4259
  5. package/dist/ag-q9lRlKlt.mjs.map +1 -0
  6. package/dist/{animation-ZMN2_XKv.mjs → animation-CZ4x2R7C.mjs} +1 -1
  7. package/dist/{animation-ZMN2_XKv.mjs.map → animation-CZ4x2R7C.mjs.map} +1 -1
  8. package/dist/{ansi-D1KQMAbf.mjs → ansi-CLmIMnop.mjs} +1 -1
  9. package/dist/{ansi-D1KQMAbf.mjs.map → ansi-CLmIMnop.mjs.map} +1 -1
  10. package/dist/{ansi-2Xn0yatP.d.mts → ansi-zmNzgkPB.d.mts} +1 -1
  11. package/dist/{ansi-2Xn0yatP.d.mts.map → ansi-zmNzgkPB.d.mts.map} +1 -1
  12. package/dist/{backend-B-WYLUib.mjs → backend-DSiSIc-h.mjs} +2 -2
  13. package/dist/{backend-B-WYLUib.mjs.map → backend-DSiSIc-h.mjs.map} +1 -1
  14. package/dist/chain-bridge-CkYcMxlq.mjs +4149 -0
  15. package/dist/chain-bridge-CkYcMxlq.mjs.map +1 -0
  16. package/dist/{chunk-BSw8zbkd.mjs → chunk-BEJ448es.mjs} +1 -3
  17. package/dist/cli-VNqUKlXw.mjs +4 -0
  18. package/dist/{context-BU5LkkIy.mjs → context-CEhuD1R_.mjs} +1 -1
  19. package/dist/{context-BU5LkkIy.mjs.map → context-CEhuD1R_.mjs.map} +1 -1
  20. package/dist/devtools-BF4IMumr.mjs +2 -0
  21. package/dist/{devtools-DcQjgyjL.mjs → devtools-td2AjFwc.mjs} +5 -5
  22. package/dist/{devtools-DcQjgyjL.mjs.map → devtools-td2AjFwc.mjs.map} +1 -1
  23. package/dist/{easing-BI-ASGMO.d.mts → easing-C5MrdO7V.d.mts} +1 -1
  24. package/dist/{easing-BI-ASGMO.d.mts.map → easing-C5MrdO7V.d.mts.map} +1 -1
  25. package/dist/{eta-CJlGH06n.mjs → eta-BwYWEjfS.mjs} +1 -1
  26. package/dist/{eta-CJlGH06n.mjs.map → eta-BwYWEjfS.mjs.map} +1 -1
  27. package/dist/{flexily-zero-adapter-C4lW_Ov5.mjs → flexily-zero-adapter-DktX3HsX.mjs} +1 -1
  28. package/dist/{flexily-zero-adapter-C3Vj0fPt.mjs → flexily-zero-adapter-VoBGHG14.mjs} +1 -1
  29. package/dist/{flexily-zero-adapter-C3Vj0fPt.mjs.map → flexily-zero-adapter-VoBGHG14.mjs.map} +1 -1
  30. package/dist/hit-registry-D_nxOivS.d.mts +71 -0
  31. package/dist/hit-registry-D_nxOivS.d.mts.map +1 -0
  32. package/dist/{UPNG-DosRPdF4.mjs → image-CIF75xMr.mjs} +891 -6
  33. package/dist/image-CIF75xMr.mjs.map +1 -0
  34. package/dist/{index-CSQf13CI.d.mts → index-377zdPLP.d.mts} +35 -12
  35. package/dist/index-377zdPLP.d.mts.map +1 -0
  36. package/dist/{index-Cl9KKjQ_.d.mts → index-BcSr0RAQ.d.mts} +8670 -10659
  37. package/dist/index-BcSr0RAQ.d.mts.map +1 -0
  38. package/dist/{index-XbNrPhWl.d.mts → index-DLnpxDAm.d.mts} +2 -2
  39. package/dist/{index-XbNrPhWl.d.mts.map → index-DLnpxDAm.d.mts.map} +1 -1
  40. package/dist/{index-BUMxS65f.d.mts → index-DlNmckTq.d.mts} +2 -2
  41. package/dist/{index-BUMxS65f.d.mts.map → index-DlNmckTq.d.mts.map} +1 -1
  42. package/dist/index.d.mts +12 -8
  43. package/dist/index.d.mts.map +1 -1
  44. package/dist/index.mjs +18 -15
  45. package/dist/index.mjs.map +1 -1
  46. package/dist/{layout-engine-C2px0RJE.mjs → layout-engine-BgR58vL0.mjs} +3 -3
  47. package/dist/{layout-engine-C2px0RJE.mjs.map → layout-engine-BgR58vL0.mjs.map} +1 -1
  48. package/dist/{layout-engine-C07LEXWT.mjs → layout-engine-DNjTha8f.mjs} +1 -1
  49. package/dist/{layout-signals-Cnw6xk8Q.mjs → layout-signals-CGYbHmxy.mjs} +146 -23
  50. package/dist/layout-signals-CGYbHmxy.mjs.map +1 -0
  51. package/dist/{bound-term-0sPrrzH1.d.mts → mouse-events-B2z5tbsL.d.mts} +780 -379
  52. package/dist/mouse-events-B2z5tbsL.d.mts.map +1 -0
  53. package/dist/{mouse-events-Dki3ISIp.mjs → mouse-events-WQ2h-uqG.mjs} +45 -10
  54. package/dist/mouse-events-WQ2h-uqG.mjs.map +1 -0
  55. package/dist/{multi-progress-DHZ2xUT2.d.mts → multi-progress-BaEFfHKP.d.mts} +2 -2
  56. package/dist/{multi-progress-DHZ2xUT2.d.mts.map → multi-progress-BaEFfHKP.d.mts.map} +1 -1
  57. package/dist/{multi-progress-CIRjrzma.mjs → multi-progress-zCWHEm9P.mjs} +3 -3
  58. package/dist/{multi-progress-CIRjrzma.mjs.map → multi-progress-zCWHEm9P.mjs.map} +1 -1
  59. package/dist/{node-CjM5Rt-M.mjs → node-CJ3J_rW-.mjs} +1 -1
  60. package/dist/{node-CjM5Rt-M.mjs.map → node-CJ3J_rW-.mjs.map} +1 -1
  61. package/dist/{progress-DB_Xo071.mjs → progress-6vJ7nxUg.mjs} +4 -4
  62. package/dist/{progress-DB_Xo071.mjs.map → progress-6vJ7nxUg.mjs.map} +1 -1
  63. package/dist/{progress-bar-oJwq22CR.mjs → progress-bar-BlFNsZL8.mjs} +4 -4
  64. package/dist/{progress-bar-oJwq22CR.mjs.map → progress-bar-BlFNsZL8.mjs.map} +1 -1
  65. package/dist/{reconciler-DldIJB93.mjs → reconciler--_-biN23.mjs} +190 -134
  66. package/dist/reconciler--_-biN23.mjs.map +1 -0
  67. package/dist/{render-string-BcoCpjCB.mjs → render-string-DaghHpLN.mjs} +1 -1
  68. package/dist/render-string-DtHZP0cU.mjs +215 -0
  69. package/dist/render-string-DtHZP0cU.mjs.map +1 -0
  70. package/dist/runtime.d.mts +4 -3
  71. package/dist/runtime.mjs +4 -3
  72. package/dist/schemes-DWQPxXAi.mjs +2516 -0
  73. package/dist/{schemes-JjNp4aSl.mjs.map → schemes-DWQPxXAi.mjs.map} +1 -1
  74. package/dist/{spinner-D9lrHr8s.mjs → spinner-B50hILqx.mjs} +19 -4
  75. package/dist/{spinner-D9lrHr8s.mjs.map → spinner-B50hILqx.mjs.map} +1 -1
  76. package/dist/{spinner-CZINHpkV.d.mts → spinner-DN10UfF0.d.mts} +2 -2
  77. package/dist/{spinner-CZINHpkV.d.mts.map → spinner-DN10UfF0.d.mts.map} +1 -1
  78. package/dist/{src-BNTToU7l.mjs → src-B8lf1kiR.mjs} +1507 -1166
  79. package/dist/src-B8lf1kiR.mjs.map +1 -0
  80. package/dist/{src-5w9QR6_8.mjs → src-BOLdi3WG.mjs} +105 -237
  81. package/dist/src-BOLdi3WG.mjs.map +1 -0
  82. package/dist/{src-BR4xNwdG.mjs → src-BXeTHHlL.mjs} +20240 -25437
  83. package/dist/src-BXeTHHlL.mjs.map +1 -0
  84. package/dist/{src-DKp-_OFG.mjs → src-BqeBFB3X.mjs} +90 -47
  85. package/dist/src-BqeBFB3X.mjs.map +1 -0
  86. package/dist/src-DbqcSrhy.mjs +3901 -0
  87. package/dist/src-DbqcSrhy.mjs.map +1 -0
  88. package/dist/{steps-Bp2uNqnn.d.mts → steps-B2kBmFpb.d.mts} +1 -1
  89. package/dist/{steps-Bp2uNqnn.d.mts.map → steps-B2kBmFpb.d.mts.map} +1 -1
  90. package/dist/{svg-Cz0UXcDj.mjs → svg-NmV9dgB9.mjs} +1 -1
  91. package/dist/{svg-Cz0UXcDj.mjs.map → svg-NmV9dgB9.mjs.map} +1 -1
  92. package/dist/{svg-g1D6ErwR.d.mts → svg-VUr78l5d.d.mts} +1 -1
  93. package/dist/{svg-g1D6ErwR.d.mts.map → svg-VUr78l5d.d.mts.map} +1 -1
  94. package/dist/term.d.mts +2 -2
  95. package/dist/term.mjs +3 -8
  96. package/dist/test.d.mts +673 -0
  97. package/dist/test.d.mts.map +1 -0
  98. package/dist/test.mjs +2829 -0
  99. package/dist/test.mjs.map +1 -0
  100. package/dist/theme.d.mts +2 -2
  101. package/dist/theme.d.mts.map +1 -1
  102. package/dist/theme.mjs +3 -8
  103. package/dist/{types-kt_fKR37.d.mts → types-D_E0FbqA.d.mts} +1 -1
  104. package/dist/{types-kt_fKR37.d.mts.map → types-D_E0FbqA.d.mts.map} +1 -1
  105. package/dist/ui/animation.d.mts +2 -2
  106. package/dist/ui/animation.mjs +1 -1
  107. package/dist/ui/ansi.d.mts +1 -1
  108. package/dist/ui/ansi.mjs +1 -1
  109. package/dist/ui/cli.d.mts +3 -3
  110. package/dist/ui/cli.mjs +5 -5
  111. package/dist/ui/image.d.mts +1 -1
  112. package/dist/ui/image.mjs +1 -1
  113. package/dist/ui/progress.d.mts +4 -4
  114. package/dist/ui/progress.mjs +4 -4
  115. package/dist/ui/react.d.mts +1 -1
  116. package/dist/ui/react.mjs +2 -2
  117. package/dist/ui/recording-chrome-react.d.mts +1 -1
  118. package/dist/ui/recording-chrome-react.mjs +2 -2
  119. package/dist/ui/recording-chrome.d.mts +1 -1
  120. package/dist/ui/recording-chrome.mjs +1 -1
  121. package/dist/ui/utils.mjs +1 -1
  122. package/dist/ui/wrappers.d.mts +2 -2
  123. package/dist/ui/wrappers.mjs +1 -1
  124. package/dist/ui.d.mts +6 -6
  125. package/dist/ui.mjs +7 -7
  126. package/dist/unicode-CxyxVGmB.mjs +11077 -0
  127. package/dist/unicode-CxyxVGmB.mjs.map +1 -0
  128. package/dist/{useLatest-DRDDVwjh.d.mts → useLatest-UOvWy0ZW.d.mts} +2 -2
  129. package/dist/{useLatest-DRDDVwjh.d.mts.map → useLatest-UOvWy0ZW.d.mts.map} +1 -1
  130. package/dist/useLayout-D5cE8OCI.mjs +424 -0
  131. package/dist/useLayout-D5cE8OCI.mjs.map +1 -0
  132. package/dist/{with-text-input-YeohVLeo.d.mts → with-text-input-DLoSCBrm.d.mts} +3 -3
  133. package/dist/{with-text-input-YeohVLeo.d.mts.map → with-text-input-DLoSCBrm.d.mts.map} +1 -1
  134. package/dist/wrap-measurer-registration-IV2HtcCd.d.mts +3106 -0
  135. package/dist/wrap-measurer-registration-IV2HtcCd.d.mts.map +1 -0
  136. package/dist/{wrapper-C70ATkVv.mjs → wrapper-CD29afOs.mjs} +59 -17
  137. package/dist/wrapper-CD29afOs.mjs.map +1 -0
  138. package/dist/{wrappers-BCUYITrY.mjs → wrappers-CInBJm44.mjs} +18 -8
  139. package/dist/wrappers-CInBJm44.mjs.map +1 -0
  140. package/dist/{yoga-adapter-BnZX1PAY.mjs → yoga-adapter-9uab5Qn-.mjs} +2 -2
  141. package/dist/{yoga-adapter-BnZX1PAY.mjs.map → yoga-adapter-9uab5Qn-.mjs.map} +1 -1
  142. package/dist/yoga-adapter-yqTl1aXK.mjs +2 -0
  143. package/package.json +59 -14
  144. package/dist/Text-Lq0dmj8-.mjs.map +0 -1
  145. package/dist/UPNG-Bo33r8rA.mjs +0 -3
  146. package/dist/UPNG-DosRPdF4.mjs.map +0 -1
  147. package/dist/__vite-browser-external-2447137e-D_JM6skp.mjs +0 -6
  148. package/dist/__vite-browser-external-2447137e-D_JM6skp.mjs.map +0 -1
  149. package/dist/ansi-yC4RyBNY.mjs +0 -22441
  150. package/dist/ansi-yC4RyBNY.mjs.map +0 -1
  151. package/dist/apng-CR08rIaH.mjs +0 -58
  152. package/dist/apng-CR08rIaH.mjs.map +0 -1
  153. package/dist/apng-DaHfVaVI.mjs +0 -3
  154. package/dist/assets/resvgjs.darwin-arm64-BtufyGW1.node +0 -0
  155. package/dist/assets/skia.darwin-arm64-DQs5sT6N.node +0 -0
  156. package/dist/backends-CUtan80W.mjs +0 -3
  157. package/dist/backends-DIVYzKqd.mjs +0 -1083
  158. package/dist/backends-DIVYzKqd.mjs.map +0 -1
  159. package/dist/bound-term-0sPrrzH1.d.mts.map +0 -1
  160. package/dist/canvas-1v7dPT-_.mjs +0 -3
  161. package/dist/canvas-CSuPOMNt.mjs +0 -1442
  162. package/dist/canvas-CSuPOMNt.mjs.map +0 -1
  163. package/dist/cli-dvo0r2fs.mjs +0 -4
  164. package/dist/compare-CQodSH4G.mjs +0 -376
  165. package/dist/compare-CQodSH4G.mjs.map +0 -1
  166. package/dist/compare-DHlcxEYA.mjs +0 -3
  167. package/dist/devtools-CJdt5H0X.mjs +0 -2
  168. package/dist/fonts-BFmhXDv7.mjs +0 -88
  169. package/dist/fonts-BFmhXDv7.mjs.map +0 -1
  170. package/dist/gif-C_AjaT9d.mjs +0 -188
  171. package/dist/gif-C_AjaT9d.mjs.map +0 -1
  172. package/dist/gif-DaC4XrxA.mjs +0 -3
  173. package/dist/gifenc-BOUT-KFB.mjs +0 -730
  174. package/dist/gifenc-BOUT-KFB.mjs.map +0 -1
  175. package/dist/image-C2Birh2x.mjs +0 -1252
  176. package/dist/image-C2Birh2x.mjs.map +0 -1
  177. package/dist/index-CSQf13CI.d.mts.map +0 -1
  178. package/dist/index-Cl9KKjQ_.d.mts.map +0 -1
  179. package/dist/key-mapping-CS-YD_cD.mjs +0 -132
  180. package/dist/key-mapping-CS-YD_cD.mjs.map +0 -1
  181. package/dist/key-mapping-Yn-Jgrij.mjs +0 -3
  182. package/dist/layout-signals-Cnw6xk8Q.mjs.map +0 -1
  183. package/dist/mouse-events-Dki3ISIp.mjs.map +0 -1
  184. package/dist/playwright-D5YiZcNS.mjs +0 -76397
  185. package/dist/playwright-D5YiZcNS.mjs.map +0 -1
  186. package/dist/png-codec-Dp84742B.mjs +0 -36
  187. package/dist/png-codec-Dp84742B.mjs.map +0 -1
  188. package/dist/png-codec-QwOtJ8Zs.mjs +0 -3
  189. package/dist/rasterizer-BRXrDdWx.mjs +0 -3
  190. package/dist/rasterizer-CpEhJvdR.mjs +0 -296
  191. package/dist/rasterizer-CpEhJvdR.mjs.map +0 -1
  192. package/dist/reconciler-DldIJB93.mjs.map +0 -1
  193. package/dist/render-string-DkQacASz.mjs.map +0 -1
  194. package/dist/resvg-js-DkOndZI3.mjs +0 -203
  195. package/dist/resvg-js-DkOndZI3.mjs.map +0 -1
  196. package/dist/schemes-JjNp4aSl.mjs +0 -2611
  197. package/dist/src-5w9QR6_8.mjs.map +0 -1
  198. package/dist/src-BNTToU7l.mjs.map +0 -1
  199. package/dist/src-BR4xNwdG.mjs.map +0 -1
  200. package/dist/src-DKp-_OFG.mjs.map +0 -1
  201. package/dist/src-bt8wSrfJ.mjs +0 -258
  202. package/dist/src-bt8wSrfJ.mjs.map +0 -1
  203. package/dist/src-e33Y6kNJ.mjs +0 -3
  204. package/dist/src-iDwu25UD.mjs +0 -1814
  205. package/dist/src-iDwu25UD.mjs.map +0 -1
  206. package/dist/svg-15lZZzxq.mjs +0 -486
  207. package/dist/svg-15lZZzxq.mjs.map +0 -1
  208. package/dist/svg-DY72a4HK.mjs +0 -3
  209. package/dist/term.mjs.map +0 -1
  210. package/dist/theme.mjs.map +0 -1
  211. package/dist/ui/display.d.mts +0 -35
  212. package/dist/ui/display.d.mts.map +0 -1
  213. package/dist/ui/display.mjs +0 -123
  214. package/dist/ui/display.mjs.map +0 -1
  215. package/dist/ui/input.d.mts +0 -184
  216. package/dist/ui/input.d.mts.map +0 -1
  217. package/dist/ui/input.mjs +0 -285
  218. package/dist/ui/input.mjs.map +0 -1
  219. package/dist/wrapper-C70ATkVv.mjs.map +0 -1
  220. package/dist/wrappers-BCUYITrY.mjs.map +0 -1
  221. package/dist/yoga-adapter-DxgsQ_gg.mjs +0 -2
  222. package/dist/zipBundle-3nqeDRtm.mjs +0 -3
  223. package/dist/zipBundle-VNAYFmqJ.mjs +0 -2003
  224. package/dist/zipBundle-VNAYFmqJ.mjs.map +0 -1
@@ -1,5 +1,4 @@
1
- import { M as RGB$1, N as UnderlineStyle$2, P as TerminalCaps, j as ColorLevel, mt as Theme, yt as TerminalEmulator, z as TerminalProfile } from "./index-CSQf13CI.mjs";
2
- import * as _$react from "react";
1
+ import { B as TerminalProfile, F as TerminalCaps, M as RGB$1, N as TerminalNotificationProtocol, P as UnderlineStyle$2, bt as TerminalEmulator, ht as Theme, j as ColorLevel } from "./index-377zdPLP.mjs";
3
2
 
4
3
  //#region packages/ag/src/viewport-types.d.ts
5
4
  /**
@@ -480,6 +479,41 @@ interface IslandMouseEvent {
480
479
  shift?: boolean;
481
480
  alt?: boolean;
482
481
  }
482
+ /**
483
+ * Host command-prefix reservation for a focused input-capable island (the tmux
484
+ * `Ctrl-b` model, @hab/.../20349). When set on a focused island, the runtime
485
+ * routes a matching key to the HOST (it falls through to the app's `useInput`)
486
+ * instead of feeding the guest — letting a multi-pane host (e.g. a deck shell
487
+ * pane) keep a command prefix while a full-screen guest owns every other key.
488
+ *
489
+ * This is a deliberately NARROW concept — it names host-owned deck/control keys,
490
+ * not arbitrary interception. A key is reserved for the host iff it matches
491
+ * `hotkey`, one of `reservedHotkeys`, OR `capturing` is true.
492
+ */
493
+ interface IslandCommandPrefix {
494
+ /**
495
+ * The always-reserved prefix hotkey, in {@link import("./keys").parseHotkey}
496
+ * syntax (e.g. `"ctrl+g"`, `"Control+b"`). Matched against each key via
497
+ * {@link import("./keys").matchHotkey}. The prefix never reaches the guest
498
+ * while the island is focused.
499
+ */
500
+ hotkey: string;
501
+ /**
502
+ * Additional single-step host hotkeys reserved even when the host is not
503
+ * mid-command. Use this for direct deck navigation shortcuts that must not
504
+ * leak into a focused full-screen guest (for example Option+h/j/k/l pane
505
+ * focus). These keys fall through to host `useInput` just like `hotkey`.
506
+ */
507
+ reservedHotkeys?: readonly string[];
508
+ /**
509
+ * Host is mid-command (a chord/menu is pending). While `true`, EVERY key is
510
+ * reserved for the host (routed to `useInput`, not the guest) so multi-key
511
+ * chord follow-ups reach the host until it clears the flag. A deck typically
512
+ * binds this to its `chordPending` state. Default behavior when omitted:
513
+ * `false` — only the `hotkey` and `reservedHotkeys` are reserved.
514
+ */
515
+ capturing?: boolean;
516
+ }
483
517
  /**
484
518
  * Modes owner — host queries which protocol modes the guest currently wants
485
519
  * active (alt-screen, bracketed-paste, mouse-tracking SGR, Kitty keyboard,
@@ -719,6 +753,28 @@ interface IslandNodeState {
719
753
  focusable: boolean;
720
754
  /** True iff this island is currently in the focused subtree. */
721
755
  focused: boolean;
756
+ /**
757
+ * Host-designated cursor activation, INDEPENDENT of input focus
758
+ * (@km/silvery/19426). When true, `findActiveCursorRect` renders this
759
+ * island's guest cursor (`handle.output.cursor` + `cursorVisible`) as the
760
+ * host hardware caret, translated into the island's screen rect. The host
761
+ * is responsible for the one-cursor invariant — at most one island should
762
+ * carry `cursorActive` at a time (e.g. silvermux sets it for the focused
763
+ * pane only). Lets a host show a pane caret without giving the island input
764
+ * focus (which would route keys away from the host's own input handler).
765
+ */
766
+ cursorActive?: boolean;
767
+ /**
768
+ * Host command prefix (tmux model, @hab/.../20349). When set and this island
769
+ * is the focused input target, the runtime reserves a matching key for the
770
+ * host — it falls through to the app's `useInput` instead of feeding the
771
+ * guest. A key is reserved iff it matches `commandPrefix.hotkey`, one of
772
+ * `commandPrefix.reservedHotkeys`, OR `commandPrefix.capturing` is true.
773
+ * Absent ⇒ the guest captures every key (default behavior). Lets a host keep
774
+ * command keys (e.g. `Ctrl-G`, Option pane navigation) while a full-screen
775
+ * guest owns the rest. Set by `<Island commandPrefix={…}>`.
776
+ */
777
+ commandPrefix?: IslandCommandPrefix;
722
778
  /**
723
779
  * Effective palette policy. Frozen palette: snapshot held in
724
780
  * `frozenPalette`. Inherit: `null` (host theme cascades).
@@ -752,15 +808,21 @@ interface IslandNodeState {
752
808
  interface DragEventPayload {
753
809
  /** The node being dragged */
754
810
  source: AgNode;
755
- /** Current terminal position of the pointer */
811
+ /** Current Silvery layout-space position of the pointer */
756
812
  position: {
757
813
  x: number;
758
814
  y: number;
759
815
  };
760
- /** The node under the cursor (the drop target receiving this event) */
816
+ /** The current or final drop target under the pointer, when one exists */
761
817
  dropTarget: AgNode | null;
762
818
  }
763
819
  interface DragEventProps {
820
+ /** Fired on the draggable source when the pointer crosses the drag threshold */
821
+ onDragStart?: (event: DragEventPayload) => void;
822
+ /** Fired on the draggable source after pointer release, whether or not a drop target exists */
823
+ onDragEnd?: (event: DragEventPayload) => void;
824
+ /** Fired on the draggable source when an active drag is canceled */
825
+ onDragCancel?: (event: DragEventPayload) => void;
764
826
  /** Fired when a dragged node enters this node's bounds */
765
827
  onDragEnter?: (event: DragEventPayload) => void;
766
828
  /** Fired when a dragged node leaves this node's bounds */
@@ -781,15 +843,17 @@ interface DragEventProps {
781
843
  *
782
844
  * parseKey() returns `[input, key]` where these serve DIFFERENT purposes:
783
845
  *
784
- * - `input` is **normalized for keybinding matching**. Shifted punctuation is
846
+ * - `input` is **normalized for physical keybinding matching**. Shifted punctuation is
785
847
  * decomposed: '#' becomes input='3' with key.shift=true, so keybindings
786
- * like 'shift-3' can match. Uppercase letters become lowercase + shift.
848
+ * like 'shift+3' can match. Uppercase letters retain their casing and set shift.
787
849
  *
788
850
  * - `key.text` is the **actual typed character** (pre-normalization). For text
789
- * insertion, always use `key.text ?? input` this ensures Shift+3 inserts
790
- * '#', opt+e inserts '´', and IME output inserts the composed string.
851
+ * insertion or literal-character hotkeys, use it instead of normalized `input`.
852
+ * `key.text ?? input` ensures Shift+3 inserts '#', opt+e inserts '´', and IME
853
+ * output inserts the composed string.
791
854
  *
792
- * Rule: keybinding resolution uses `input`. Text insertion uses `key.text`.
855
+ * Rule: physical keybindings use `input` plus modifiers. Literal-character hotkeys
856
+ * and text insertion use `key.text`; matchHotkey() handles both representations.
793
857
  * Never reconstruct characters from key codes — trust what the terminal sent.
794
858
  *
795
859
  * - KEY_MAP: Playwright key names -> ANSI sequences (for sending input)
@@ -897,6 +961,32 @@ interface ParsedHotkey {
897
961
  super: boolean;
898
962
  hyper: boolean;
899
963
  }
964
+ /**
965
+ * Convert Playwright-style key string to ANSI sequence.
966
+ *
967
+ * Supports:
968
+ * - Single characters: 'a', 'A', '1', etc.
969
+ * - Named keys: 'Enter', 'ArrowUp', 'Escape', etc.
970
+ * - Modifier combos: 'Control+c', 'Shift+Tab', 'Control+Shift+a'
971
+ * - Lowercase modifier aliases: 'ctrl+c', 'shift+Tab', 'alt+x'
972
+ *
973
+ * @example
974
+ * ```tsx
975
+ * keyToAnsi('Enter') // '\r'
976
+ * keyToAnsi('ArrowUp') // '\x1b[A'
977
+ * keyToAnsi('Control+c') // '\x03'
978
+ * keyToAnsi('j') // 'j'
979
+ * ```
980
+ */
981
+ declare function keyToAnsi(key: string): string;
982
+ /**
983
+ * ANSI escape code suffix -> key name mapping.
984
+ * Used by useInput to parse incoming key sequences.
985
+ *
986
+ * The key is the escape sequence suffix (after ESC or ESC[).
987
+ * Multiple terminal emulators may use different sequences for the same key.
988
+ */
989
+ declare const CODE_TO_KEY: Record<string, string>;
900
990
  interface ParsedKeypress {
901
991
  name: string;
902
992
  ctrl: boolean;
@@ -997,6 +1087,24 @@ declare function parseHotkey(keyStr: string): ParsedHotkey;
997
1087
  * @returns true if the hotkey matches the key event
998
1088
  */
999
1089
  declare function matchHotkey(hotkey: ParsedHotkey, key: Key, input?: string): boolean;
1090
+ /**
1091
+ * Convert a Playwright-style key string to a Kitty keyboard protocol ANSI sequence.
1092
+ *
1093
+ * Uses the appropriate Kitty format for each key type:
1094
+ * - Regular keys: CSI codepoint ; modifiers u
1095
+ * - Arrow/nav keys: CSI 1 ; modifiers letter (enhanced special key format)
1096
+ * - Tilde keys: CSI number ; modifiers ~ (enhanced special key format)
1097
+ *
1098
+ * @example
1099
+ * ```tsx
1100
+ * keyToKittyAnsi('a') // '\x1b[97u' (no modifiers → bare)
1101
+ * keyToKittyAnsi('Enter') // '\x1b[13u'
1102
+ * keyToKittyAnsi('Control+c') // '\x1b[99;5u' (ctrl = 4, modifier = 5)
1103
+ * keyToKittyAnsi('Shift+Enter') // '\x1b[13;2u' (shift = 1, modifier = 2)
1104
+ * keyToKittyAnsi('ArrowUp') // '\x1b[1;1A' (enhanced special key)
1105
+ * ```
1106
+ */
1107
+ declare function keyToKittyAnsi(key: string): string;
1000
1108
  //#endregion
1001
1109
  //#region packages/ag/src/focus-events.d.ts
1002
1110
  /**
@@ -1285,9 +1393,13 @@ interface SilveryMouseEvent {
1285
1393
  * Synthetic wheel event, extending SilveryMouseEvent with scroll deltas.
1286
1394
  */
1287
1395
  interface SilveryWheelEvent extends SilveryMouseEvent {
1288
- /** Vertical scroll: -1 (up) or +1 (down) */
1396
+ /** Vertical scroll: -1 (up), +1 (down), or 0 for a pure-horizontal wheel */
1289
1397
  deltaY: number;
1290
- /** Horizontal scroll: always 0 for terminals */
1398
+ /**
1399
+ * Horizontal scroll: -1 (left), +1 (right), or 0 for a pure-vertical wheel.
1400
+ * Sourced from SGR mouse buttons 66/67 (trackpad / tilt-wheel horizontal
1401
+ * scroll); 0 on terminals or input devices that never emit them.
1402
+ */
1291
1403
  deltaX: number;
1292
1404
  }
1293
1405
  interface MouseEventProps {
@@ -1317,6 +1429,14 @@ interface MouseEventProps {
1317
1429
  * keeps its CSS meaning as an explicit hard boundary.
1318
1430
  */
1319
1431
  type UserSelect = "auto" | "none" | "text" | "contain";
1432
+ /**
1433
+ * Semantic mouse pointer intent for the region occupied by a Box.
1434
+ *
1435
+ * Terminal renderers map this to OSC 22 cursor names; DOM/canvas targets can
1436
+ * map the same vocabulary to CSS cursor values. Unsupported terminal targets
1437
+ * silently ignore the emitted OSC sequence.
1438
+ */
1439
+ type MouseCursorShape = "default" | "text" | "pointer" | "crosshair" | "move" | "not-allowed" | "wait" | "help" | "grab" | "grabbing" | "col-resize" | "row-resize" | "ew-resize" | "ns-resize";
1320
1440
  /**
1321
1441
  * A rectangle with position and size.
1322
1442
  * All values are in terminal columns/rows (integers).
@@ -1798,8 +1918,9 @@ interface BoxProps extends FlexboxProps, StyleProps, TestProps, MouseEventProps,
1798
1918
  /**
1799
1919
  * Whether this node can be dragged via mouse.
1800
1920
  * When true, mousedown + drag past threshold initiates a node drag gesture
1801
- * instead of text selection. Not inherited only the node with draggable=true
1802
- * is draggable, not its children.
1921
+ * instead of text selection. The prop is not inherited, but pointer hits on
1922
+ * descendants resolve to their nearest draggable ancestor, matching DOM drag
1923
+ * targeting for content-bearing cards and rows.
1803
1924
  */
1804
1925
  draggable?: boolean;
1805
1926
  /**
@@ -1812,6 +1933,22 @@ interface BoxProps extends FlexboxProps, StyleProps, TestProps, MouseEventProps,
1812
1933
  * narrow draggable controls such as scrollbars.
1813
1934
  */
1814
1935
  mouseCapture?: boolean;
1936
+ /**
1937
+ * Semantic mouse cursor for this hit-test region.
1938
+ *
1939
+ * The deepest hovered node with a cursor wins; if the deepest hit node has no
1940
+ * cursor, the resolver walks ancestors so a parent region can provide the
1941
+ * default affordance for its children. During `mouseCapture`, the capture
1942
+ * target owns the cursor so drags keep their grab/resize shape outside the
1943
+ * original one-cell hit box.
1944
+ *
1945
+ * When omitted, activation handlers derive `"pointer"` and selectable text
1946
+ * derives `"text"`. Explicit values always win; pass `"default"` to opt out
1947
+ * of semantic defaults and restore the target's native cursor.
1948
+ *
1949
+ * @default Derived from interaction semantics.
1950
+ */
1951
+ mouseCursor?: MouseCursorShape;
1815
1952
  onLayout?: (layout: Rect) => void;
1816
1953
  /**
1817
1954
  * Show scroll overflow indicators (▲N / ▼N) for scrollable containers.
@@ -1868,9 +2005,13 @@ interface BoxProps extends FlexboxProps, StyleProps, TestProps, MouseEventProps,
1868
2005
  * across conditional mounts (see `km-silvercode.cursor-startup-position`).
1869
2006
  *
1870
2007
  * **Precedence across nodes** (locked by `km-silvery.cursor-invariants` #1):
1871
- * 1. Focused-editable wins — a Box that is `focused` AND has visible
1872
- * `cursorOffset` always beats a non-focused declarer.
1873
- * 2. Otherwise deepest-in-paint-order (post-order tree walk) wins.
2008
+ * 1. Focused cursor owner wins — a Box that has `cursorOffset` and either
2009
+ * `focused === true` or focus-manager `interactiveState.focused === true`
2010
+ * always beats a non-focused declarer, even when
2011
+ * `cursorOffset.visible === false`. Hidden focused owners still carry a
2012
+ * position so terminal renderers can move there before hiding the
2013
+ * hardware cursor.
2014
+ * 2. Otherwise deepest visible in paint order (post-order tree walk) wins.
1874
2015
  * 3. Otherwise null.
1875
2016
  *
1876
2017
  * **Clipping** (invariant #4): if the caret falls outside the nearest
@@ -1879,6 +2020,23 @@ interface BoxProps extends FlexboxProps, StyleProps, TestProps, MouseEventProps,
1879
2020
  * clip edge is treated as visible.
1880
2021
  */
1881
2022
  cursorOffset?: CursorOffset;
2023
+ /**
2024
+ * Component-relative HARDWARE-PARK cell. Declares where a managed terminal
2025
+ * frame parks (then hides) the hardware cursor when this Box owns the frame —
2026
+ * position-only (`col`/`row`; `visible`/`shape` are ignored — the visible
2027
+ * caret is `cursorOffset`'s job).
2028
+ *
2029
+ * UNLIKE `cursorOffset`, park is **not focus-gated**: an editable declares its
2030
+ * input cell here whether or not it (or the window) is focused, so a managed
2031
+ * frame ALWAYS has a benign park cell. This is the structural fix for the
2032
+ * recurring "hardware cursor parks one row above the prompt" bug
2033
+ * (@km/code/v0.2/19702): with no park declaration the frame fell back to the
2034
+ * box origin / `home(0,0)`, and a multiplexer that dropped the cursor-hide
2035
+ * surfaced the parked cursor there. Resolved by `computeParkRect` + the
2036
+ * non-focus-gated tree walk `findActiveParkRect`; consumed by
2037
+ * `managedCursorSuffix`.
2038
+ */
2039
+ parkOffset?: CursorOffset;
1882
2040
  /**
1883
2041
  * Semantic selection intent — the user's selected substring within this
1884
2042
  * Box's text content, declared as character offsets `{ from, to }`. The
@@ -2096,6 +2254,67 @@ interface TextFlexItemProps {
2096
2254
  /** CSS `max-height`. */
2097
2255
  maxHeight?: number | string;
2098
2256
  }
2257
+ /**
2258
+ * Cell-width-aware measurement helpers handed to a {@link TextTruncateHook}.
2259
+ * Every method counts display columns (CJK / emoji are 2 cells), never code
2260
+ * units — so a hook can implement its own elision policy without re-deriving
2261
+ * width math. Backed by the active pipeline measurer when present, module-level
2262
+ * fallbacks otherwise.
2263
+ */
2264
+ interface TextMeasure {
2265
+ /** Display width (terminal columns) of `text`. */
2266
+ width(text: string): number;
2267
+ /** Longest prefix of `text` whose display width is <= `max` columns. */
2268
+ sliceByWidth(text: string, max: number): string;
2269
+ /** Longest suffix of `text` whose display width is <= `max` columns. */
2270
+ sliceByWidthFromEnd(text: string, max: number): string;
2271
+ }
2272
+ /**
2273
+ * Rich result a {@link TextTruncateHook} may return instead of a bare string,
2274
+ * so a policy hook can mark which spans of its fitted line are elision-marker
2275
+ * CHROME (e.g. a `" … "` separator) rather than content. Marker spans render
2276
+ * with {@link TextProps.truncateMarkerColor} (default `"$fg-muted"`), making
2277
+ * the elision read as quiet chrome instead of competing with the surrounding
2278
+ * text.
2279
+ *
2280
+ * A bare `string` return is exactly equivalent to `{ text }` with no markers —
2281
+ * today's behavior, no marker styling of hook output.
2282
+ */
2283
+ interface TextTruncateResult {
2284
+ /** The fitted line. Same contract as a bare-string return — defensively
2285
+ * hard-clipped if it still overflows, so the hook can never paint past the
2286
+ * box edge. */
2287
+ text: string;
2288
+ /**
2289
+ * JS string-index `[start, end)` ranges within `text` that are
2290
+ * elision-marker chrome, rendered with {@link TextProps.truncateMarkerColor}.
2291
+ * Indices are UTF-16 offsets into `text` (the PLAIN visible string the hook
2292
+ * was handed and returned — never the inline-ANSI form). Out-of-bounds or
2293
+ * overlapping ranges are clamped / ignored defensively (a STRICT-mode warning
2294
+ * is emitted); a malformed `markers` array never throws in production paths.
2295
+ */
2296
+ markers?: readonly {
2297
+ start: number;
2298
+ end: number;
2299
+ }[];
2300
+ }
2301
+ /**
2302
+ * Per-line truncation hook for `wrap` truncate modes. Only consulted when the
2303
+ * line OVERFLOWS the available width; receives the overflowing `line`, the
2304
+ * available cell `width`, and a cell-width-aware {@link TextMeasure}.
2305
+ *
2306
+ * Return the fitted line (bare `string`), a {@link TextTruncateResult} to also
2307
+ * mark marker-chrome spans, or `null` to fall back to the built-in truncation
2308
+ * for the active mode. The returned text is NOT trusted blindly — if it still
2309
+ * overflows, the pipeline hard-clips it via `measure.sliceByWidth`, so a hook
2310
+ * can never paint past the box edge. Returning `null` MUST be cheap and safe;
2311
+ * the hook runs once per overflowing line, every render.
2312
+ *
2313
+ * This is where width-dependent elision policy lives (e.g. a tail-length
2314
+ * formula derived from `width`), which a static data prop cannot express.
2315
+ * Function-prop precedent in `TextProps`: the mouse handlers.
2316
+ */
2317
+ type TextTruncateHook = (line: string, width: number, measure: TextMeasure) => string | TextTruncateResult | null;
2099
2318
  interface TextProps extends StyleProps, TextFlexItemProps, TestProps, MouseEventProps {
2100
2319
  children?: React.ReactNode;
2101
2320
  /**
@@ -2119,6 +2338,47 @@ interface TextProps extends StyleProps, TextFlexItemProps, TestProps, MouseEvent
2119
2338
  * cells).
2120
2339
  */
2121
2340
  wrap?: "wrap" | "wrap-truncate" | "hard" | "even" | "truncate" | "truncate-start" | "truncate-middle" | "truncate-end" | "clip" | boolean;
2341
+ /**
2342
+ * Per-line truncation hook. Only consulted when `wrap` is a truncate mode
2343
+ * (`"truncate"` / `"truncate-start"` / `"truncate-middle"` / `"truncate-end"`)
2344
+ * AND the line overflows the available width. Lets the consumer supply a
2345
+ * width-dependent elision policy (custom separator, token-boundary breaks,
2346
+ * slug rescue) the built-in modes can't express. Returns the fitted line or
2347
+ * `null` to use the built-in truncation. An overwide return value is
2348
+ * defensively hard-clipped — the hook can never paint past the box edge.
2349
+ * See {@link TextTruncateHook}.
2350
+ */
2351
+ truncate?: TextTruncateHook;
2352
+ /**
2353
+ * Color for elision-marker CHROME in truncated output — the inserted "…" of
2354
+ * the built-in truncate modes (`"truncate"` / `"truncate-end"` /
2355
+ * `"truncate-start"` / `"truncate-middle"` / `"wrap-truncate"`) AND any
2356
+ * marker ranges a {@link TextTruncateHook} returns via
2357
+ * {@link TextTruncateResult.markers}. Styling the marker separately from the
2358
+ * surrounding text lets the elision read as quiet chrome, not content.
2359
+ *
2360
+ * Accepts the same color forms as {@link StyleProps.color} (`$token`, hex,
2361
+ * named, `rgb(...)`, `mix(...)`), resolved against the active theme at paint
2362
+ * time. Does NOT affect the surrounding text — only the marker cells.
2363
+ *
2364
+ * Defaults to `"$fg-muted"` (the standard low/dim fg slot), NOT `"$muted"` —
2365
+ * in the default pipeline theme `"$muted"` resolves to the same value as
2366
+ * `"$fg"`, so it would never dim against `$fg`-colored text.
2367
+ *
2368
+ * @default "$fg-muted"
2369
+ */
2370
+ truncateMarkerColor?: string;
2371
+ /** @internal Hyperlink carried as cell metadata; use Link instead. */
2372
+ internal_hyperlink?: string;
2373
+ /**
2374
+ * @internal Faint/dim text — SGR 2. Intentionally NOT a public style prop:
2375
+ * the design system is token-first, so reach for a semantic token
2376
+ * (`$fg-muted`, `$muted`, …) instead. This escape hatch exists only for
2377
+ * chrome on surfaces with no matching token tier (e.g. dimmed text on the
2378
+ * `$bg-inverse` band). Prefer tokens everywhere a token exists. Inherited by
2379
+ * nested `<Text>`; a child's explicit value wins.
2380
+ */
2381
+ internal_dim?: boolean;
2122
2382
  /** Internal transform function applied to each rendered line. Used by Transform component. */
2123
2383
  internal_transform?: (line: string, index: number) => string;
2124
2384
  /**
@@ -2142,6 +2402,16 @@ interface TextProps extends StyleProps, TextFlexItemProps, TestProps, MouseEvent
2142
2402
  * global mode (`SILVERY_BG_CONFLICT`, default `"throw"`).
2143
2403
  */
2144
2404
  bgConflict?: "ignore" | "warn" | "throw";
2405
+ /**
2406
+ * Semantic mouse cursor for this text hit-test region.
2407
+ *
2408
+ * Uses the same resolver as `BoxProps.mouseCursor`: explicit hovered
2409
+ * regions win, activation ancestors derive `"pointer"`, and selectable text
2410
+ * derives `"text"`. Pass `"default"` to opt out of those defaults.
2411
+ *
2412
+ * @default Derived from interaction semantics.
2413
+ */
2414
+ mouseCursor?: MouseCursorShape;
2145
2415
  }
2146
2416
  /**
2147
2417
  * The core Silvery node - represents an element in the render tree.
@@ -2465,6 +2735,146 @@ interface EventSource {
2465
2735
  [Symbol.asyncIterator](): AsyncIterator<Event>;
2466
2736
  }
2467
2737
  //#endregion
2738
+ //#region packages/ag/src/focus-manager.d.ts
2739
+ type FocusOrigin = "keyboard" | "mouse" | "programmatic";
2740
+ /**
2741
+ * Callback fired when focus changes. Used by the runtime to dispatch
2742
+ * DOM-level focus/blur events without coupling FocusManager to the event system.
2743
+ *
2744
+ * @param oldNode - The node losing focus (null if nothing was focused)
2745
+ * @param newNode - The node gaining focus (null on blur)
2746
+ * @param origin - How focus was acquired
2747
+ */
2748
+ type FocusChangeCallback = (oldNode: AgNode | null, newNode: AgNode | null, origin: FocusOrigin | null) => void;
2749
+ interface FocusSnapshot {
2750
+ activeId: string | null;
2751
+ previousId: string | null;
2752
+ focusOrigin: FocusOrigin | null;
2753
+ scopeStack: readonly string[];
2754
+ /** The currently active peer scope (WPF FocusScope model) */
2755
+ activeScopeId: string | null;
2756
+ }
2757
+ interface FocusManagerOptions {
2758
+ /** Called when focus changes — wire up event dispatch here */
2759
+ onFocusChange?: FocusChangeCallback;
2760
+ }
2761
+ /**
2762
+ * Options for registering a hook-based (virtual) focusable.
2763
+ *
2764
+ * Hook focusables are registered via React hooks (e.g. `useFocus()` in the
2765
+ * Ink compat layer) rather than by the `focusable` prop on a tree node. They
2766
+ * participate in Tab cycling but don't have a backing `AgNode` — activeId
2767
+ * tracking is by id only, and `activeElement` is null when a hook focusable
2768
+ * is the active target.
2769
+ */
2770
+ interface HookFocusableOptions {
2771
+ /** Registration is inert when false — skipped in tab order, never reports focused */
2772
+ isActive?: boolean;
2773
+ /** Focus this id when registered (only when isActive !== false) */
2774
+ autoFocus?: boolean;
2775
+ }
2776
+ interface FocusManager {
2777
+ /** Currently focused node */
2778
+ readonly activeElement: AgNode | null;
2779
+ /** testID of the currently focused node */
2780
+ readonly activeId: string | null;
2781
+ /** Previously focused node */
2782
+ readonly previousElement: AgNode | null;
2783
+ /** testID of the previously focused node */
2784
+ readonly previousId: string | null;
2785
+ /** How focus was most recently acquired */
2786
+ readonly focusOrigin: FocusOrigin | null;
2787
+ /** Stack of active focus scope IDs */
2788
+ readonly scopeStack: readonly string[];
2789
+ /** Map of scope ID -> last focused testID within that scope */
2790
+ readonly scopeMemory: Readonly<Record<string, string>>;
2791
+ /** Focus a specific node */
2792
+ focus(node: AgNode, origin?: FocusOrigin): void;
2793
+ /** Focus a node by testID (requires root for tree search) */
2794
+ focusById(id: string, root: AgNode, origin?: FocusOrigin): void;
2795
+ /**
2796
+ * Focus a hook-registered (virtual) id directly without tree traversal.
2797
+ * Unlike `focusById`, this never needs a root — used by `useFocus()` hooks
2798
+ * that track focus by id only.
2799
+ */
2800
+ focusVirtualId(id: string, origin?: FocusOrigin): void;
2801
+ /** Clear focus */
2802
+ blur(): void;
2803
+ /**
2804
+ * Register a hook-based focusable id (e.g. from `useFocus()` in Ink compat).
2805
+ *
2806
+ * Hook focusables form a flat list alongside the tree-based focusables.
2807
+ * `focusNext`/`focusPrev` interleave: tree focusables come first (document
2808
+ * order), then hook focusables (registration order). A single unified tab
2809
+ * cycle walks both.
2810
+ *
2811
+ * Returns an unregister callback (safe to call on effect cleanup).
2812
+ */
2813
+ registerHookFocusable(id: string, options?: HookFocusableOptions): () => void;
2814
+ /** Update an existing hook-focusable's active state. */
2815
+ setHookFocusableActive(id: string, isActive: boolean): void;
2816
+ /** Whether any hook focusables are currently registered. */
2817
+ readonly hasHookFocusables: boolean;
2818
+ /**
2819
+ * Global focus enable (Ink compat). When false, `focusNext`/`focusPrev`
2820
+ * become no-ops for hook-registered focusables. Tree-based focusables
2821
+ * ignore this flag — apps using `useFocusable` are not affected.
2822
+ */
2823
+ readonly hookFocusEnabled: boolean;
2824
+ setHookFocusEnabled(enabled: boolean): void;
2825
+ /**
2826
+ * Handle a subtree being removed from the tree.
2827
+ * If the focused node (or previous node) is within the removed subtree,
2828
+ * clear the reference to prevent dead node retention and broken navigation.
2829
+ */
2830
+ handleSubtreeRemoved(removedRoot: AgNode): void;
2831
+ /**
2832
+ * Handle a mounted node's props/state being updated.
2833
+ * If the active focus target is no longer focusable or has become hidden,
2834
+ * clear focus so focused-element input dispatch falls back to host handlers.
2835
+ * Symmetrically, if VIRTUAL focus is pending (`activeId` set, no
2836
+ * `activeElement`) and this update made the matching node focusable, promote
2837
+ * it to real focus (Law 3 — looks-focused ≡ receives-input; 20992 f2).
2838
+ */
2839
+ handleNodeUpdated(updatedNode: AgNode): void;
2840
+ /**
2841
+ * Handle a subtree being ATTACHED to the tree (commit-phase mount or move).
2842
+ * If virtual focus is pending and the subtree carries a focusable node whose
2843
+ * testID matches `activeId`, promote it to real focus — the intent landed
2844
+ * before the node existed, and no consumer retry should be needed (the hab
2845
+ * 20989 looks-focused-but-no-input class; 20992 f2). O(1) unless virtual
2846
+ * focus is actually pending.
2847
+ */
2848
+ handleSubtreeAttached(attachedRoot: AgNode): void;
2849
+ /** Push a focus scope onto the stack */
2850
+ enterScope(scopeId: string): void;
2851
+ /** Pop the current focus scope */
2852
+ exitScope(): void;
2853
+ /** The currently active peer scope ID (WPF FocusScope model) */
2854
+ readonly activeScopeId: string | null;
2855
+ /**
2856
+ * Activate a peer focus scope. Saves current focus in the old scope's memory,
2857
+ * switches to the new scope, and restores the remembered focus (or focuses
2858
+ * the first focusable element in the scope subtree).
2859
+ */
2860
+ activateScope(scopeId: string, root: AgNode): void;
2861
+ /** Get the testID path from focused node to root */
2862
+ getFocusPath(root: AgNode): string[];
2863
+ /** Check if a subtree rooted at testID contains the focused node */
2864
+ hasFocusWithin(root: AgNode, testID: string): boolean;
2865
+ /** Focus the next focusable node in tab order */
2866
+ focusNext(root: AgNode, scope?: AgNode): void;
2867
+ /** Focus the previous focusable node in tab order */
2868
+ focusPrev(root: AgNode, scope?: AgNode): void;
2869
+ /** Focus in a spatial direction (up/down/left/right) */
2870
+ focusDirection(root: AgNode, direction: "up" | "down" | "left" | "right", layoutFn?: (node: AgNode) => Rect | null): void;
2871
+ /** Subscribe for React integration (useSyncExternalStore) */
2872
+ subscribe(listener: () => void): () => void;
2873
+ /** Get immutable snapshot for useSyncExternalStore */
2874
+ getSnapshot(): FocusSnapshot;
2875
+ }
2876
+ declare function createFocusManager(options?: FocusManagerOptions): FocusManager;
2877
+ //#endregion
2468
2878
  //#region packages/ag-term/src/mouse.d.ts
2469
2879
  /**
2470
2880
  * SGR mouse event parsing (mode 1006) and SGR-Pixels parsing (mode 1016).
@@ -2503,8 +2913,18 @@ interface ParsedMouse {
2503
2913
  coordinateMode: "cell" | "pixel";
2504
2914
  /** Event action */
2505
2915
  action: "down" | "up" | "move" | "wheel";
2506
- /** Wheel delta: -1 for up, +1 for down */
2916
+ /**
2917
+ * Vertical wheel delta (deltaY): -1 for wheel-up, +1 for wheel-down, 0 for a
2918
+ * pure-horizontal wheel. DOM-style sign convention (down is positive).
2919
+ */
2507
2920
  delta?: number;
2921
+ /**
2922
+ * Horizontal wheel delta (deltaX): -1 for wheel-left, +1 for wheel-right, 0
2923
+ * for a pure-vertical wheel. DOM-style sign convention (right is positive).
2924
+ * SGR buttons 66 (left) / 67 (right) decode here; consumers that only read
2925
+ * `delta`/`deltaY` are unaffected.
2926
+ */
2927
+ deltaX?: number;
2508
2928
  /** Shift was held */
2509
2929
  shift: boolean;
2510
2930
  /** Alt/Meta was held */
@@ -2675,12 +3095,22 @@ interface TermEmulatorBackend {
2675
3095
  * @packageDocumentation
2676
3096
  */
2677
3097
  /**
2678
- * RGB color value (0-255 per channel).
3098
+ * RGB color value (0-255 per channel), with optional palette provenance.
3099
+ *
3100
+ * `r`/`g`/`b` are always present and resolved — painters read them
3101
+ * unconditionally. `index` optionally preserves the origin 256-color palette
3102
+ * slot (0-255) when the color came from an indexed entry (`ansi256(N)`, or an
3103
+ * engine cell carrying identity-preserving color); only identity-aware code
3104
+ * (differs, re-emitters, comparators) touches it. This shape is structurally
3105
+ * compatible with termless's `Color = { r, g, b, index? }` — the two are
3106
+ * compared by shape, never imported across the silvery↔termless boundary.
2679
3107
  */
2680
3108
  interface RGB {
2681
3109
  r: number;
2682
3110
  g: number;
2683
3111
  b: number;
3112
+ /** Origin 256-color palette slot (0-255), when the color was indexed. */
3113
+ index?: number;
2684
3114
  }
2685
3115
  /**
2686
3116
  * A single cell in a TextFrame with resolved styling.
@@ -2746,13 +3176,6 @@ interface TextFrame {
2746
3176
  }
2747
3177
  //#endregion
2748
3178
  //#region packages/ag-term/src/buffer.d.ts
2749
- /**
2750
- * Terminal buffer implementation for Silvery.
2751
- *
2752
- * Uses packed Uint32Array for efficient cell metadata storage,
2753
- * with separate string array for character storage (needed for
2754
- * multi-byte Unicode graphemes and combining characters).
2755
- */
2756
3179
  /**
2757
3180
  * Underline style variants (SGR 4:x codes).
2758
3181
  * - false: no underline
@@ -2790,8 +3213,11 @@ interface CellAttrs {
2790
3213
  }
2791
3214
  /**
2792
3215
  * Color representation.
2793
- * - number: 256-color index (0-255)
2794
- * - RGB object: true color
3216
+ * - number: 256-color index (0-255) — silvery's compact indexed form
3217
+ * - RGB object: true color; may carry `index` to preserve palette provenance
3218
+ * (identity-preserving color — the shape the terminal-flow engine produces).
3219
+ * When `index` is a valid 0-255 slot it is honored ahead of r/g/b, so the
3220
+ * color packs and re-emits as indexed SGR rather than a truecolor bake.
2795
3221
  * - null: default/inherit
2796
3222
  * - DEFAULT_BG: terminal's default background (SGR 49), opaque but uses terminal's own bg color
2797
3223
  */
@@ -2799,6 +3225,7 @@ type Color = number | {
2799
3225
  r: number;
2800
3226
  g: number;
2801
3227
  b: number;
3228
+ index?: number;
2802
3229
  } | null;
2803
3230
  /**
2804
3231
  * A single cell in the terminal buffer.
@@ -2865,6 +3292,19 @@ interface RowMetadata {
2865
3292
  softWrapped: boolean;
2866
3293
  /** Rightmost column with non-space content (for trailing space trimming) */
2867
3294
  lastContentCol: number;
3295
+ /**
3296
+ * Only meaningful when `softWrapped` is true. Records whether the soft-wrap
3297
+ * break to the next row consumed a whitespace character (word wrap) versus a
3298
+ * forced mid-word break (a token longer than the line, or `wrap="hard"`).
3299
+ *
3300
+ * `trim`-mode rendering (the default) strips the breaking space from BOTH
3301
+ * rows, so copy extraction must reinsert exactly one separator when rejoining
3302
+ * the visual rows into their logical line: a single space when
3303
+ * `wrapJoinSpace` is true, nothing when it is false/undefined. Without this,
3304
+ * "alpha beta gamma"+"delta" rejoins as "alpha beta gammadelta" (lost space)
3305
+ * and "verylong"+"word" would gain a spurious space.
3306
+ */
3307
+ wrapJoinSpace?: boolean;
2868
3308
  }
2869
3309
  /**
2870
3310
  * Efficient terminal cell buffer.
@@ -3112,6 +3552,18 @@ declare class TerminalBuffer {
3112
3552
  * the runtime's prevBuffer skipped intermediate buffers).
3113
3553
  */
3114
3554
  markAllRowsDirty(): void;
3555
+ /**
3556
+ * Mark a single row as dirty (no-op if out of bounds).
3557
+ *
3558
+ * Used by the managed-caret overlay-clear path: when a composited caret is
3559
+ * suppressed or moves off a row whose CONTENT is otherwise static (and thus
3560
+ * clean in this incremental buffer), the prior caret's row must be made dirty
3561
+ * so `diffBuffers` re-scans it and clears the stale `inverse` overlay cell.
3562
+ * Without this, the dirty-row gate (`diffBuffers`: `if (!next.isRowDirty(y))
3563
+ * continue`) skips the row and the prior frame's reverse-video block strands
3564
+ * on screen — the @km/code/v0.2/19702 cursor-above-composer signature.
3565
+ */
3566
+ markRowDirty(y: number): void;
3115
3567
  /**
3116
3568
  * Check if two cells at given positions are equal.
3117
3569
  * Used for diffing.
@@ -3138,6 +3590,105 @@ declare class TerminalBuffer {
3138
3590
  */
3139
3591
  rowExtrasEquals(y: number, other: TerminalBuffer): boolean;
3140
3592
  }
3593
+ /**
3594
+ * Convert a terminal buffer to plain text (no ANSI codes).
3595
+ * Useful for snapshot testing and text-based assertions.
3596
+ *
3597
+ * @param buffer The buffer to convert
3598
+ * @param options.trimTrailingWhitespace Remove trailing spaces from each line (default: true)
3599
+ * @param options.trimEmptyLines Remove trailing empty lines (default: true)
3600
+ * @returns Plain text representation of the buffer
3601
+ */
3602
+ declare function bufferToText(buffer: TerminalBuffer, options?: {
3603
+ trimTrailingWhitespace?: boolean;
3604
+ trimEmptyLines?: boolean;
3605
+ }): string;
3606
+ /**
3607
+ * Convert a terminal buffer to styled ANSI text.
3608
+ * Unlike bufferToAnsi, this doesn't include cursor control sequences,
3609
+ * making it suitable for displaying in terminals or saving to files.
3610
+ *
3611
+ * @param buffer The buffer to convert
3612
+ * @param options.trimTrailingWhitespace Remove trailing spaces from each line (default: true)
3613
+ * @param options.trimEmptyLines Remove trailing empty lines (default: true)
3614
+ * @returns ANSI-styled text (no cursor control)
3615
+ */
3616
+ declare function bufferToStyledText(buffer: TerminalBuffer, options?: {
3617
+ trimTrailingWhitespace?: boolean;
3618
+ trimEmptyLines?: boolean;
3619
+ colorLevel?: ColorLevel;
3620
+ }): string;
3621
+ /**
3622
+ * Convert a terminal buffer to a full HTML document.
3623
+ * Suitable for rendering as a screenshot via headless browser.
3624
+ *
3625
+ * @param buffer The buffer to convert
3626
+ * @param options.fontFamily CSS font-family (default: 'JetBrains Mono, Menlo, monospace')
3627
+ * @param options.fontSize CSS font-size in px (default: 14)
3628
+ * @param options.theme Color scheme (default: 'dark')
3629
+ * @returns Complete HTML document string
3630
+ */
3631
+ declare function bufferToHTML(buffer: TerminalBuffer, options?: {
3632
+ fontFamily?: string;
3633
+ fontSize?: number;
3634
+ theme?: "dark" | "light";
3635
+ }): string;
3636
+ //#endregion
3637
+ //#region packages/ag-term/src/ansi/notification.d.ts
3638
+ type NotificationUrgency = "low" | "normal" | "critical";
3639
+ /** Target-neutral action shown alongside a desktop notification. */
3640
+ interface NotificationAction {
3641
+ /** Stable application-owned id returned by activation events. */
3642
+ readonly id: string;
3643
+ readonly label: string;
3644
+ }
3645
+ /** Protocol-neutral notification data accepted by a Term. */
3646
+ interface NotificationRequest {
3647
+ /** Stable identifier used by protocols that support replacement. */
3648
+ readonly id?: string;
3649
+ readonly title?: string;
3650
+ readonly body: string;
3651
+ readonly urgency?: NotificationUrgency;
3652
+ /** Optional actions. The terminal target supports these only through OSC 99. */
3653
+ readonly actions?: readonly NotificationAction[];
3654
+ /** Ask the target to report a click on the notification itself. */
3655
+ readonly reportActivation?: boolean;
3656
+ }
3657
+ type NotificationUnsupportedReason = "notifications" | "notification-actions" | "notification-activation";
3658
+ /** Target-neutral delivery result shared by terminal and future DOM targets. */
3659
+ type NotificationDelivery = {
3660
+ readonly status: "emitted";
3661
+ } | {
3662
+ readonly status: "unsupported";
3663
+ readonly reason: NotificationUnsupportedReason;
3664
+ };
3665
+ /** Terminal refinement that preserves exact protocol evidence for Term callers. */
3666
+ type TerminalNotificationDelivery = {
3667
+ readonly status: "emitted";
3668
+ readonly protocol: TerminalNotificationProtocol;
3669
+ } | {
3670
+ readonly status: "unsupported";
3671
+ readonly reason: NotificationUnsupportedReason;
3672
+ };
3673
+ /** Target-neutral activation projected from the target's native reply. */
3674
+ type NotificationActivation = {
3675
+ readonly id: string;
3676
+ readonly kind: "notification";
3677
+ } | {
3678
+ readonly id: string;
3679
+ readonly kind: "action";
3680
+ readonly actionId: string;
3681
+ };
3682
+ /** Cross-target notification capability. A future DOM target implements this same shape. */
3683
+ interface NotificationTarget {
3684
+ notify(request: NotificationRequest): NotificationDelivery;
3685
+ onNotificationActivation(handler: (event: NotificationActivation) => void): () => void;
3686
+ }
3687
+ /** OSC 99 reply after protocol parsing, before domain action-id projection. */
3688
+ interface TerminalNotificationActivation {
3689
+ readonly id: string;
3690
+ readonly button?: number;
3691
+ }
3141
3692
  //#endregion
3142
3693
  //#region packages/signals/src/index.d.ts
3143
3694
  /**
@@ -3228,6 +3779,23 @@ interface Modes extends Disposable {
3228
3779
  readonly mouse: Signal<MouseTrackingMode>;
3229
3780
  /** Focus-in / focus-out reporting (DEC 1004). */
3230
3781
  readonly focusReporting: Signal<boolean>;
3782
+ /**
3783
+ * Disable DEC private mode 1007 (alternate-scroll) with `CSI ?1007l`.
3784
+ *
3785
+ * Alternate-scroll makes the terminal translate wheel events into cursor
3786
+ * (arrow) keys while the alternate screen is active and mouse tracking is
3787
+ * OFF. For a silvery app that deliberately turned mouse tracking off, those
3788
+ * synthesized arrows move the cursor/selection on every wheel tick — the
3789
+ * recurring "wheel jumps the cursor" bug. Disabling 1007 turns the wheel
3790
+ * into a benign no-op instead.
3791
+ *
3792
+ * One-way by design, unlike the callable-signal modes above: we emit
3793
+ * `?1007l` at most once and never re-enable on dispose. 1007's prior state
3794
+ * is unknowable (we never query it), so a blind `?1007h` on teardown could
3795
+ * wrongly enable a mode the user had off; and it is moot once we leave the
3796
+ * alt screen, which is where 1007 has any effect. Idempotent across calls.
3797
+ */
3798
+ disableAlternateScroll(): void;
3231
3799
  /**
3232
3800
  * Enable a mode and return a `Disposable` that restores the mode to its
3233
3801
  * prior value on disposal. Complements the per-mode signals for callers
@@ -3329,6 +3897,13 @@ interface InputOwner extends Disposable {
3329
3897
  * unsubscribe function.
3330
3898
  */
3331
3899
  onFocus(handler: (event: FocusEvent) => void): () => void;
3900
+ /** Subscribe to parsed OSC 99 activation replies. */
3901
+ onNotificationActivationReply(handler: (event: TerminalNotificationActivation) => void): () => void;
3902
+ /**
3903
+ * Inject raw terminal input through the canonical parser. Emulator-backed
3904
+ * Terms use this instead of maintaining a second protocol parser.
3905
+ */
3906
+ sendRaw(data: string | Buffer): void;
3332
3907
  /**
3333
3908
  * Inject a synthetic key event. Used by emulator-backed terms
3334
3909
  * (`createTerm({ cols, rows, emulator })`) and test helpers to fan out to
@@ -3365,11 +3940,12 @@ interface InputOwnerOptions {
3365
3940
  /**
3366
3941
  * When true, `dispose()` does NOT drop raw mode. The listener is still
3367
3942
  * removed and pending probes still resolve with null, but raw mode stays
3368
- * set so the next owner (typically the term-provider's events() generator)
3369
- * can take over seamlessly.
3943
+ * set for a caller-managed handoff.
3370
3944
  *
3371
- * Use this when the owner is the pre-session probe window AND a follow-up
3372
- * stdin consumer will re-set raw=true immediately.
3945
+ * Silvery's runtime does not use this escape hatch: probes and normal input
3946
+ * share one owner instead. Removing a listener while raw mode remains set
3947
+ * creates an ownerless interval unless the caller supplies stronger atomic
3948
+ * handoff machinery than Node streams provide.
3373
3949
  */
3374
3950
  retainRawModeOnDispose?: boolean;
3375
3951
  /**
@@ -3831,7 +4407,7 @@ readonly [K in ChalkStyleName]: StyleChain } & {
3831
4407
  * await run(<App />, term)
3832
4408
  * ```
3833
4409
  */
3834
- interface Term extends Disposable, StyleChain {
4410
+ interface Term extends Disposable, StyleChain, NotificationTarget {
3835
4411
  /**
3836
4412
  * Terminal capabilities profile.
3837
4413
  *
@@ -3894,7 +4470,7 @@ interface Term extends Disposable, StyleChain {
3894
4470
  /**
3895
4471
  * Input owner — mediates ALL stdin reads + raw-mode + data subscription.
3896
4472
  * Use `term.input.probe(…)` for terminal queries (color, cursor, kitty, etc.)
3897
- * and `term.input.onData(…)` for primary key/mouse stream consumers.
4473
+ * and its typed key/mouse/paste/focus subscriptions for normal input.
3898
4474
  *
3899
4475
  * Replaces direct `process.stdin.setRawMode` / `stdin.on('data', …)` —
3900
4476
  * those patterns race under async (the 2026-04-22 wasRaw class).
@@ -3994,6 +4570,10 @@ interface Term extends Disposable, StyleChain {
3994
4570
  * Write string to stdout.
3995
4571
  */
3996
4572
  write(str: string): void;
4573
+ /** Emit a desktop notification through the capability-proven protocol. */
4574
+ notify(request: NotificationRequest): TerminalNotificationDelivery;
4575
+ /** Subscribe to target-neutral notification and action activations. */
4576
+ onNotificationActivation(handler: (event: NotificationActivation) => void): () => void;
3997
4577
  /**
3998
4578
  * Write string followed by newline to stdout.
3999
4579
  */
@@ -4102,136 +4682,14 @@ declare function createTerm(emulator: TermEmulator, opts?: {
4102
4682
  //#region packages/ag-term/src/ansi/index.d.ts
4103
4683
  declare const term: Term;
4104
4684
  //#endregion
4105
- //#region packages/ag/src/focus-manager.d.ts
4106
- type FocusOrigin = "keyboard" | "mouse" | "programmatic";
4107
- /**
4108
- * Callback fired when focus changes. Used by the runtime to dispatch
4109
- * DOM-level focus/blur events without coupling FocusManager to the event system.
4110
- *
4111
- * @param oldNode - The node losing focus (null if nothing was focused)
4112
- * @param newNode - The node gaining focus (null on blur)
4113
- * @param origin - How focus was acquired
4114
- */
4115
- type FocusChangeCallback = (oldNode: AgNode | null, newNode: AgNode | null, origin: FocusOrigin | null) => void;
4116
- interface FocusSnapshot {
4117
- activeId: string | null;
4118
- previousId: string | null;
4119
- focusOrigin: FocusOrigin | null;
4120
- scopeStack: readonly string[];
4121
- /** The currently active peer scope (WPF FocusScope model) */
4122
- activeScopeId: string | null;
4685
+ //#region packages/headless/src/selection.d.ts
4686
+ interface SelectionPosition {
4687
+ col: number;
4688
+ row: number;
4123
4689
  }
4124
- interface FocusManagerOptions {
4125
- /** Called when focus changes — wire up event dispatch here */
4126
- onFocusChange?: FocusChangeCallback;
4127
- }
4128
- /**
4129
- * Options for registering a hook-based (virtual) focusable.
4130
- *
4131
- * Hook focusables are registered via React hooks (e.g. `useFocus()` in the
4132
- * Ink compat layer) rather than by the `focusable` prop on a tree node. They
4133
- * participate in Tab cycling but don't have a backing `AgNode` — activeId
4134
- * tracking is by id only, and `activeElement` is null when a hook focusable
4135
- * is the active target.
4136
- */
4137
- interface HookFocusableOptions {
4138
- /** Registration is inert when false — skipped in tab order, never reports focused */
4139
- isActive?: boolean;
4140
- /** Focus this id when registered (only when isActive !== false) */
4141
- autoFocus?: boolean;
4142
- }
4143
- interface FocusManager {
4144
- /** Currently focused node */
4145
- readonly activeElement: AgNode | null;
4146
- /** testID of the currently focused node */
4147
- readonly activeId: string | null;
4148
- /** Previously focused node */
4149
- readonly previousElement: AgNode | null;
4150
- /** testID of the previously focused node */
4151
- readonly previousId: string | null;
4152
- /** How focus was most recently acquired */
4153
- readonly focusOrigin: FocusOrigin | null;
4154
- /** Stack of active focus scope IDs */
4155
- readonly scopeStack: readonly string[];
4156
- /** Map of scope ID -> last focused testID within that scope */
4157
- readonly scopeMemory: Readonly<Record<string, string>>;
4158
- /** Focus a specific node */
4159
- focus(node: AgNode, origin?: FocusOrigin): void;
4160
- /** Focus a node by testID (requires root for tree search) */
4161
- focusById(id: string, root: AgNode, origin?: FocusOrigin): void;
4162
- /**
4163
- * Focus a hook-registered (virtual) id directly without tree traversal.
4164
- * Unlike `focusById`, this never needs a root — used by `useFocus()` hooks
4165
- * that track focus by id only.
4166
- */
4167
- focusVirtualId(id: string, origin?: FocusOrigin): void;
4168
- /** Clear focus */
4169
- blur(): void;
4170
- /**
4171
- * Register a hook-based focusable id (e.g. from `useFocus()` in Ink compat).
4172
- *
4173
- * Hook focusables form a flat list alongside the tree-based focusables.
4174
- * `focusNext`/`focusPrev` interleave: tree focusables come first (document
4175
- * order), then hook focusables (registration order). A single unified tab
4176
- * cycle walks both.
4177
- *
4178
- * Returns an unregister callback (safe to call on effect cleanup).
4179
- */
4180
- registerHookFocusable(id: string, options?: HookFocusableOptions): () => void;
4181
- /** Update an existing hook-focusable's active state. */
4182
- setHookFocusableActive(id: string, isActive: boolean): void;
4183
- /** Whether any hook focusables are currently registered. */
4184
- readonly hasHookFocusables: boolean;
4185
- /**
4186
- * Global focus enable (Ink compat). When false, `focusNext`/`focusPrev`
4187
- * become no-ops for hook-registered focusables. Tree-based focusables
4188
- * ignore this flag — apps using `useFocusable` are not affected.
4189
- */
4190
- readonly hookFocusEnabled: boolean;
4191
- setHookFocusEnabled(enabled: boolean): void;
4192
- /**
4193
- * Handle a subtree being removed from the tree.
4194
- * If the focused node (or previous node) is within the removed subtree,
4195
- * clear the reference to prevent dead node retention and broken navigation.
4196
- */
4197
- handleSubtreeRemoved(removedRoot: AgNode): void;
4198
- /** Push a focus scope onto the stack */
4199
- enterScope(scopeId: string): void;
4200
- /** Pop the current focus scope */
4201
- exitScope(): void;
4202
- /** The currently active peer scope ID (WPF FocusScope model) */
4203
- readonly activeScopeId: string | null;
4204
- /**
4205
- * Activate a peer focus scope. Saves current focus in the old scope's memory,
4206
- * switches to the new scope, and restores the remembered focus (or focuses
4207
- * the first focusable element in the scope subtree).
4208
- */
4209
- activateScope(scopeId: string, root: AgNode): void;
4210
- /** Get the testID path from focused node to root */
4211
- getFocusPath(root: AgNode): string[];
4212
- /** Check if a subtree rooted at testID contains the focused node */
4213
- hasFocusWithin(root: AgNode, testID: string): boolean;
4214
- /** Focus the next focusable node in tab order */
4215
- focusNext(root: AgNode, scope?: AgNode): void;
4216
- /** Focus the previous focusable node in tab order */
4217
- focusPrev(root: AgNode, scope?: AgNode): void;
4218
- /** Focus in a spatial direction (up/down/left/right) */
4219
- focusDirection(root: AgNode, direction: "up" | "down" | "left" | "right", layoutFn?: (node: AgNode) => Rect | null): void;
4220
- /** Subscribe for React integration (useSyncExternalStore) */
4221
- subscribe(listener: () => void): () => void;
4222
- /** Get immutable snapshot for useSyncExternalStore */
4223
- getSnapshot(): FocusSnapshot;
4224
- }
4225
- declare function createFocusManager(options?: FocusManagerOptions): FocusManager;
4226
- //#endregion
4227
- //#region packages/headless/src/selection.d.ts
4228
- interface SelectionPosition {
4229
- col: number;
4230
- row: number;
4231
- }
4232
- interface SelectionRange {
4233
- anchor: SelectionPosition;
4234
- head: SelectionPosition;
4690
+ interface SelectionRange {
4691
+ anchor: SelectionPosition;
4692
+ head: SelectionPosition;
4235
4693
  }
4236
4694
  /**
4237
4695
  * Rectangular boundary for scoped selection.
@@ -4257,162 +4715,23 @@ interface TerminalSelectionState {
4257
4715
  scope: SelectionScope | null;
4258
4716
  }
4259
4717
  //#endregion
4260
- //#region packages/ag-term/src/mouse-events.d.ts
4261
- /**
4262
- * Create a synthetic mouse event.
4263
- *
4264
- * Modifier keys are merged from two sources:
4265
- * - SGR mouse protocol: reports Ctrl, Alt/Meta, Shift (reliable)
4266
- * - Keyboard tracking: reports Super/Cmd, Hyper, CapsLock, NumLock (via Kitty protocol)
4267
- *
4268
- * `metaKey` = keyboard-tracked Super (Cmd on macOS). SGR "meta" maps to `altKey`.
4269
- */
4270
- declare function createMouseEvent(type: SilveryMouseEvent["type"], x: number, y: number, target: AgNode, parsed: ParsedMouse, keyboardMods?: KeyboardModifierState): SilveryMouseEvent;
4271
- /**
4272
- * Create a synthetic wheel event.
4273
- */
4274
- declare function createWheelEvent(x: number, y: number, target: AgNode, parsed: ParsedMouse, keyboardMods?: KeyboardModifierState): SilveryWheelEvent;
4275
- /**
4276
- * Tree-based hit test: find the deepest node whose scrollRect contains (x, y).
4277
- *
4278
- * Uses reverse child order (last sibling wins = highest z-order, like DOM).
4279
- * Respects overflow:hidden clipping and pointerEvents="none".
4280
- *
4281
- * ### Absolute-positioned nodes escape parent bounds
4282
- *
4283
- * Absolute descendants participate in hit-testing by GEOMETRY, not by
4284
- * tree order / parent rect containment. An absolute child can be placed
4285
- * outside its parent's bounding rect (e.g., a popover anchored near a
4286
- * viewport edge); it still occupies screen cells at its own geometry and
4287
- * must be hittable.
4288
- *
4289
- * The hit test runs an "absolute pass" first that walks the whole subtree
4290
- * for absolute descendants and returns the latest-in-tree hit (matching
4291
- * the three-pass render order where absolute children paint on top of
4292
- * normal + sticky content). If no absolute descendant covers the point,
4293
- * it falls through to standard in-flow DFS.
4294
- *
4295
- * A recursive sub-call (via `hitTest(absolute, ...)`) would re-run the
4296
- * absolute pass on that absolute's subtree — which is correct: nested
4297
- * absolutes also need geometry-based hit testing.
4298
- */
4299
- declare function hitTest(node: AgNode, x: number, y: number): AgNode | null;
4300
- /**
4301
- * Dispatch a mouse event through the render tree with DOM-style bubbling.
4302
- *
4303
- * Bubbles from target → root, calling the appropriate handler on each node.
4304
- * stopPropagation() halts bubbling. mouseenter/mouseleave do NOT bubble (DOM spec).
4305
- */
4306
- declare function dispatchMouseEvent(event: SilveryMouseEvent): void;
4307
- /**
4308
- * Click-count state tracker.
4309
- *
4310
- * Counts up to 3 consecutive clicks within `MULTI_CLICK_TIME_MS` and
4311
- * `MULTI_CLICK_DISTANCE` cells of each other on the same button. After
4312
- * count reaches 3, the next click resets to 1 (matching DOM behavior:
4313
- * `MouseEvent.detail` increments to 3, then a new click chain starts).
4314
- *
4315
- * `DoubleClickState` is kept as a backwards-compatible alias.
4316
- */
4317
- interface ClickCountState {
4318
- lastClickTime: number;
4319
- lastClickX: number;
4320
- lastClickY: number;
4321
- lastClickButton: number;
4322
- /** Number of consecutive clicks in the current chain (1, 2, or 3). */
4323
- count: number;
4324
- }
4325
- /** @deprecated Use `ClickCountState` instead — kept as an alias for callers
4326
- * that haven't migrated to the count-based API. */
4327
- type DoubleClickState = ClickCountState;
4328
- declare function createClickCountState(): ClickCountState;
4329
- /** @deprecated Use `createClickCountState()` instead. */
4330
- declare const createDoubleClickState: typeof createClickCountState;
4331
- /**
4332
- * Check if a click qualifies as a double-click. Backwards-compatible
4333
- * wrapper around `checkClickCount`.
4334
- *
4335
- * @deprecated Use `checkClickCount` and inspect the returned count
4336
- * (`=== 2` for dblclick, `=== 3` for tripleclick).
4337
- */
4338
- declare function checkDoubleClick(state: ClickCountState, x: number, y: number, button: number, now?: number): boolean;
4339
- /**
4340
- * Compute mouseenter/mouseleave transitions between two ancestor paths.
4341
- *
4342
- * Returns { entered, left } — arrays of nodes that were entered or left.
4343
- * Mirrors the DOM spec: fire mouseleave on nodes in prevPath not in nextPath,
4344
- * and mouseenter on nodes in nextPath not in prevPath.
4345
- */
4346
- declare function computeEnterLeave(prevPath: AgNode[], nextPath: AgNode[]): {
4347
- entered: AgNode[];
4348
- left: AgNode[];
4349
- };
4350
- /**
4351
- * Options for creating a mouse event processor.
4352
- */
4353
- interface MouseEventProcessorOptions {
4354
- /** Optional focus manager — enables click-to-focus behavior.
4355
- * On mousedown, the deepest focusable ancestor of the hit target is focused. */
4356
- focusManager?: FocusManager;
4357
- }
4358
- /**
4359
- * State for the mouse event processor.
4360
- */
4718
+ //#region packages/ag-term/src/bound-term.d.ts
4361
4719
  /**
4362
- * Keyboard modifier state tracked from Kitty protocol key events.
4363
- * Merged into mouse events to provide accurate modifier detection
4364
- * (SGR mouse protocol reports Ctrl/Alt/Shift but NOT Cmd/Super).
4720
+ * BoundTerm interface - terminal with node awareness
4365
4721
  */
4366
- interface KeyboardModifierState {
4367
- super: boolean;
4368
- hyper: boolean;
4369
- capsLock: boolean;
4370
- numLock: boolean;
4371
- }
4372
- interface MouseEventProcessorState {
4373
- doubleClick: DoubleClickState;
4374
- /** Previous hover path (for enter/leave tracking) */
4375
- hoverPath: AgNode[];
4376
- /** Whether the left button is currently down (for click detection) */
4377
- mouseDownTarget: AgNode | null;
4378
- /** Optional ancestor that captures move/up for the active mouse press. */
4379
- mouseCaptureTarget: AgNode | null;
4380
- /** Grace timer for captured drags that briefly leave the terminal bounds. */
4381
- outsideCaptureReleaseTimer: ReturnType<typeof setTimeout> | null;
4382
- /** Last no-target mouse event observed while the grace timer is armed. */
4383
- outsideCaptureReleaseMouse: ParsedMouse | null;
4384
- /** Optional focus manager for click-to-focus */
4385
- focusManager?: FocusManager;
4386
- /** Modifier state from Kitty keyboard events, merged into mouse events */
4387
- keyboardModifiers: KeyboardModifierState;
4388
- /** Aggregate `defaultPrevented` from the most recent click/dblclick/tripleclick
4389
- * dispatch chain. Set by `processMouseEvent` on every mouseup so callers
4390
- * (e.g., the runtime selection wiring) can gate auto-select on whether the
4391
- * component tree consumed the click. Reset to false at the start of each
4392
- * mouseup dispatch. */
4393
- lastClickPrevented: boolean;
4394
- /** Last observed pointer coordinates (terminal cells). Updated on every
4395
- * mouse event so consumers can re-hit-test after layout changes — e.g.
4396
- * scroll-wheel events that reposition content under a stationary cursor.
4397
- * null means the pointer has left the terminal bounds (clearHoverPath
4398
- * ran) or no mouse event has arrived yet. */
4399
- lastPointer: {
4400
- x: number;
4401
- y: number;
4402
- } | null;
4722
+ interface BoundTerm {
4723
+ /** Get cell at screen coordinates */
4724
+ cell(x: number, y: number): Cell;
4725
+ /** Get node at screen coordinates */
4726
+ nodeAt(x: number, y: number): AgNode | null;
4727
+ /** Get visible text (plain, no ANSI) */
4728
+ readonly text: string;
4729
+ /** Terminal dimensions */
4730
+ readonly columns: number;
4731
+ readonly rows: number;
4732
+ /** Access underlying buffer */
4733
+ readonly buffer: TerminalBuffer;
4403
4734
  }
4404
- declare function createMouseEventProcessor(options?: MouseEventProcessorOptions): MouseEventProcessorState;
4405
- /**
4406
- * Process a raw ParsedMouse event and dispatch DOM-level events on the render tree.
4407
- *
4408
- * Call this for every SGR mouse event received. It handles:
4409
- * - mousedown / mouseup
4410
- * - click (on mouseup if same target as mousedown)
4411
- * - dblclick (based on timing)
4412
- * - mousemove + mouseenter/mouseleave
4413
- * - wheel
4414
- */
4415
- declare function processMouseEvent(state: MouseEventProcessorState, parsed: ParsedMouse, root: AgNode): boolean;
4416
4735
  //#endregion
4417
4736
  //#region packages/ag-term/src/hit-registry-core.d.ts
4418
4737
  /**
@@ -4552,89 +4871,171 @@ declare const Z_INDEX: {
4552
4871
  readonly TOOLTIP: 200;
4553
4872
  };
4554
4873
  //#endregion
4555
- //#region packages/ag-term/src/hit-registry.d.ts
4874
+ //#region packages/ag-term/src/mouse-events.d.ts
4556
4875
  /**
4557
- * Context for accessing the HitRegistry.
4558
- * Components use this to register their hit regions.
4876
+ * Create a synthetic mouse event.
4877
+ *
4878
+ * Modifier keys are merged from two sources:
4879
+ * - SGR mouse protocol: reports Ctrl, Alt/Meta, Shift (reliable)
4880
+ * - Keyboard tracking: reports Super/Cmd, Hyper, CapsLock, NumLock (via Kitty protocol)
4881
+ *
4882
+ * `metaKey` = keyboard-tracked Super (Cmd on macOS). SGR "meta" maps to `altKey`.
4559
4883
  */
4560
- declare const HitRegistryContext: _$react.Context<HitRegistry | null>;
4884
+ declare function createMouseEvent(type: SilveryMouseEvent["type"], x: number, y: number, target: AgNode, parsed: ParsedMouse, keyboardMods?: KeyboardModifierState): SilveryMouseEvent;
4561
4885
  /**
4562
- * Hook to get the HitRegistry from context.
4563
- *
4564
- * @returns The HitRegistry instance, or null if not in a HitRegistryContext
4886
+ * Create a synthetic wheel event.
4565
4887
  */
4566
- declare function useHitRegistry(): HitRegistry | null;
4888
+ declare function createWheelEvent(x: number, y: number, target: AgNode, parsed: ParsedMouse, keyboardMods?: KeyboardModifierState): SilveryWheelEvent;
4567
4889
  /**
4568
- * Hook to register a hit region based on component's screen position.
4890
+ * Tree-based hit test: find the deepest node whose scrollRect contains (x, y).
4569
4891
  *
4570
- * Automatically registers on mount and when position changes,
4571
- * and unregisters on unmount.
4892
+ * Uses reverse child order (last sibling wins = highest z-order, like DOM).
4893
+ * Respects overflow:hidden clipping and pointerEvents="none".
4572
4894
  *
4573
- * @param target - The target to return when this region is clicked
4574
- * @param rect - The screen rectangle (from useScrollRect or similar)
4575
- * @param zIndex - Z-index for layering (default: 0)
4576
- * @param enabled - Whether the region is active (default: true)
4895
+ * ### Absolute-positioned nodes escape parent bounds
4577
4896
  *
4578
- * @example
4579
- * ```tsx
4580
- * function Card({ nodeId }: { nodeId: string }) {
4581
- * const rect = useScrollRect();
4897
+ * Absolute descendants participate in hit-testing by GEOMETRY, not by
4898
+ * tree order / parent rect containment. An absolute child can be placed
4899
+ * outside its parent's bounding rect (e.g., a popover anchored near a
4900
+ * viewport edge); it still occupies screen cells at its own geometry and
4901
+ * must be hittable.
4582
4902
  *
4583
- * useHitRegion(
4584
- * { type: 'node', nodeId },
4585
- * rect,
4586
- * 10 // z-index for cards
4587
- * );
4903
+ * The hit test runs an "absolute pass" first that walks the whole subtree
4904
+ * for absolute descendants and returns the latest-in-tree hit (matching
4905
+ * the three-pass render order where absolute children paint on top of
4906
+ * normal + sticky content). If no absolute descendant covers the point,
4907
+ * it falls through to standard in-flow DFS.
4588
4908
  *
4589
- * return <Box>...</Box>;
4590
- * }
4591
- * ```
4909
+ * A recursive sub-call (via `hitTest(absolute, ...)`) would re-run the
4910
+ * absolute pass on that absolute's subtree — which is correct: nested
4911
+ * absolutes also need geometry-based hit testing.
4592
4912
  */
4593
- declare function useHitRegion(target: HitTarget, rect: Rect | null, zIndex?: number, enabled?: boolean): void;
4913
+ declare function hitTest(node: AgNode, x: number, y: number): AgNode | null;
4594
4914
  /**
4595
- * Hook to register a hit region using a callback for screen position.
4915
+ * Dispatch a mouse event through the render tree with DOM-style bubbling.
4596
4916
  *
4597
- * Similar to useHitRegion but works with useScrollRect for
4598
- * better performance in large lists (avoids re-renders).
4917
+ * Bubbles from target root, calling the appropriate handler on each node.
4918
+ * stopPropagation() halts bubbling. mouseenter/mouseleave do NOT bubble (DOM spec).
4919
+ */
4920
+ declare function dispatchMouseEvent(event: SilveryMouseEvent): void;
4921
+ /**
4922
+ * Click-count state tracker.
4599
4923
  *
4600
- * @param target - The target to return when this region is clicked
4601
- * @param zIndex - Z-index for layering (default: 0)
4602
- * @param enabled - Whether the region is active (default: true)
4603
- * @returns A callback to pass to useScrollRect
4924
+ * Counts up to 3 consecutive clicks within `MULTI_CLICK_TIME_MS` and
4925
+ * `MULTI_CLICK_DISTANCE` cells of each other on the same button. After
4926
+ * count reaches 3, the next click resets to 1 (matching DOM behavior:
4927
+ * `MouseEvent.detail` increments to 3, then a new click chain starts).
4604
4928
  *
4605
- * @example
4606
- * ```tsx
4607
- * function Card({ nodeId }: { nodeId: string }) {
4608
- * const onLayout = useHitRegionCallback(
4609
- * { type: 'node', nodeId },
4610
- * 10 // z-index
4611
- * );
4929
+ * `DoubleClickState` is kept as a backwards-compatible alias.
4930
+ */
4931
+ interface ClickCountState {
4932
+ lastClickTime: number;
4933
+ lastClickX: number;
4934
+ lastClickY: number;
4935
+ lastClickButton: number;
4936
+ /** Number of consecutive clicks in the current chain (1, 2, or 3). */
4937
+ count: number;
4938
+ }
4939
+ /** @deprecated Use `ClickCountState` instead — kept as an alias for callers
4940
+ * that haven't migrated to the count-based API. */
4941
+ type DoubleClickState = ClickCountState;
4942
+ declare function createClickCountState(): ClickCountState;
4943
+ /** @deprecated Use `createClickCountState()` instead. */
4944
+ declare const createDoubleClickState: typeof createClickCountState;
4945
+ /**
4946
+ * Check if a click qualifies as a double-click. Backwards-compatible
4947
+ * wrapper around `checkClickCount`.
4612
4948
  *
4613
- * useScrollRect(onLayout);
4949
+ * @deprecated Use `checkClickCount` and inspect the returned count
4950
+ * (`=== 2` for dblclick, `=== 3` for tripleclick).
4951
+ */
4952
+ declare function checkDoubleClick(state: ClickCountState, x: number, y: number, button: number, now?: number): boolean;
4953
+ /**
4954
+ * Compute mouseenter/mouseleave transitions between two ancestor paths.
4614
4955
  *
4615
- * return <Box>...</Box>;
4616
- * }
4617
- * ```
4956
+ * Returns { entered, left } — arrays of nodes that were entered or left.
4957
+ * Mirrors the DOM spec: fire mouseleave on nodes in prevPath not in nextPath,
4958
+ * and mouseenter on nodes in nextPath not in prevPath.
4618
4959
  */
4619
- declare function useHitRegionCallback(target: HitTarget, zIndex?: number, enabled?: boolean): (rect: Rect) => void;
4620
- //#endregion
4621
- //#region packages/ag-term/src/bound-term.d.ts
4960
+ declare function computeEnterLeave(prevPath: AgNode[], nextPath: AgNode[]): {
4961
+ entered: AgNode[];
4962
+ left: AgNode[];
4963
+ };
4622
4964
  /**
4623
- * BoundTerm interface - terminal with node awareness
4965
+ * Options for creating a mouse event processor.
4624
4966
  */
4625
- interface BoundTerm {
4626
- /** Get cell at screen coordinates */
4627
- cell(x: number, y: number): Cell;
4628
- /** Get node at screen coordinates */
4629
- nodeAt(x: number, y: number): AgNode | null;
4630
- /** Get visible text (plain, no ANSI) */
4631
- readonly text: string;
4632
- /** Terminal dimensions */
4633
- readonly columns: number;
4634
- readonly rows: number;
4635
- /** Access underlying buffer */
4636
- readonly buffer: TerminalBuffer;
4967
+ interface MouseEventProcessorOptions {
4968
+ /** Optional focus manager enables click-to-focus behavior.
4969
+ * On mousedown, the deepest focusable ancestor of the hit target is focused. */
4970
+ focusManager?: FocusManager;
4971
+ /**
4972
+ * Called when the semantic cursor resolved from the hit-test region changes.
4973
+ * `null` means reset to the default target cursor.
4974
+ */
4975
+ onMouseCursorChange?: (shape: BoxProps["mouseCursor"] | null) => void;
4976
+ }
4977
+ /**
4978
+ * State for the mouse event processor.
4979
+ */
4980
+ /**
4981
+ * Keyboard modifier state tracked from Kitty protocol key events.
4982
+ * Merged into mouse events to provide accurate modifier detection
4983
+ * (SGR mouse protocol reports Ctrl/Alt/Shift but NOT Cmd/Super).
4984
+ */
4985
+ interface KeyboardModifierState {
4986
+ super: boolean;
4987
+ hyper: boolean;
4988
+ capsLock: boolean;
4989
+ numLock: boolean;
4990
+ }
4991
+ interface MouseEventProcessorState {
4992
+ doubleClick: DoubleClickState;
4993
+ /** Previous hover path (for enter/leave tracking) */
4994
+ hoverPath: AgNode[];
4995
+ /** Whether the left button is currently down (for click detection) */
4996
+ mouseDownTarget: AgNode | null;
4997
+ /** Optional ancestor that captures move/up for the active mouse press. */
4998
+ mouseCaptureTarget: AgNode | null;
4999
+ /** Grace timer for captured drags that briefly leave the terminal bounds. */
5000
+ outsideCaptureReleaseTimer: ReturnType<typeof setTimeout> | null;
5001
+ /** Last no-target mouse event observed while the grace timer is armed. */
5002
+ outsideCaptureReleaseMouse: ParsedMouse | null;
5003
+ /** Optional focus manager for click-to-focus */
5004
+ focusManager?: FocusManager;
5005
+ /** Modifier state from Kitty keyboard events, merged into mouse events */
5006
+ keyboardModifiers: KeyboardModifierState;
5007
+ /** Aggregate `defaultPrevented` from the most recent click/dblclick/tripleclick
5008
+ * dispatch chain. Set by `processMouseEvent` on every mouseup so callers
5009
+ * (e.g., the runtime selection wiring) can gate auto-select on whether the
5010
+ * component tree consumed the click. Reset to false at the start of each
5011
+ * mouseup dispatch. */
5012
+ lastClickPrevented: boolean;
5013
+ /** Last observed pointer coordinates (terminal cells). Updated on every
5014
+ * mouse event so consumers can re-hit-test after layout changes — e.g.
5015
+ * scroll-wheel events that reposition content under a stationary cursor.
5016
+ * null means the pointer has left the terminal bounds (clearHoverPath
5017
+ * ran) or no mouse event has arrived yet. */
5018
+ lastPointer: {
5019
+ x: number;
5020
+ y: number;
5021
+ } | null;
5022
+ /** Last emitted semantic mouse cursor shape. */
5023
+ lastMouseCursor: BoxProps["mouseCursor"] | null;
5024
+ /** Optional callback for terminal/canvas/DOM cursor sinks. */
5025
+ onMouseCursorChange?: (shape: BoxProps["mouseCursor"] | null) => void;
4637
5026
  }
5027
+ declare function createMouseEventProcessor(options?: MouseEventProcessorOptions): MouseEventProcessorState;
5028
+ /**
5029
+ * Process a raw ParsedMouse event and dispatch DOM-level events on the render tree.
5030
+ *
5031
+ * Call this for every SGR mouse event received. It handles:
5032
+ * - mousedown / mouseup
5033
+ * - click (on mouseup if same target as mousedown)
5034
+ * - dblclick (based on timing)
5035
+ * - mousemove + mouseenter/mouseleave
5036
+ * - wheel
5037
+ */
5038
+ declare function processMouseEvent(state: MouseEventProcessorState, parsed: ParsedMouse, root: AgNode): boolean;
4638
5039
  //#endregion
4639
- export { TerminalBuffer as $, IslandGuest as $t, term as A, MeasureFunc as At, SignalOnOptions as B, Key as Bt, TerminalSelectionState as C, ResizeEvent as Ct, FocusOrigin as D, SilveryMouseEvent as Dt, FocusManagerOptions as E, MouseEventProps as Et, ConsoleCaptureOptions as F, createFocusEvent as Ft, InputOwnerOptions as G, keyToName as Gt, Signals as H, ParsedKeypress as Ht, ConsoleStats as I, createKeyEvent as It, KittyFlags as J, parseKey as Jt, createInputOwner as K, matchHotkey as Kt, createConsole as L, dispatchFocusEvent as Lt, Term as M, FocusEventProps as Mt, createTerm as N, SilveryFocusEvent as Nt, FocusSnapshot as O, SilveryWheelEvent as Ot, Console as P, SilveryKeyEvent as Pt, Style as Q, IslandCursorState as Qt, CreateSignalsOptions as R, dispatchKeyEvent as Rt, SelectionRange as S, Rect as St, FocusManager as T, TextProps as Tt, createSignals as U, emptyKey as Ut, SignalUnregister as V, ParsedHotkey as Vt, InputOwner as W, keyToModifiers as Wt, Modes as X, IslandCapabilities as Xt, ModeName as Y, parseKeypress as Yt, createModes as Z, IslandContext as Zt, createMouseEventProcessor as _, ViewportProps as _n, FocusEvent$1 as _t, useHitRegistry as a, IslandModesOwner as an, isMouseSequence as at, hitTest as b, MouseEvent as bt, HitTarget as c, IslandOutputOwner as cn, AgNodeType as ct, MouseEventProcessorOptions as d, IslandProtocolModes as dn, CollisionStrategy as dt, IslandHandle as en, UnderlineStyle as et, MouseEventProcessorState as f, IslandSignal as fn, CursorShape as ft, createMouseEvent as g, ViewportPalette as gn, EventSource as gt, createDoubleClickState as h, ForeignSource as hn, Event as ht, useHitRegionCallback as i, IslandKeyEvent as in, ParsedMouse as it, StyleChain as j, MeasureMode as jt, createFocusManager as k, LayoutNode as kt, Z_INDEX as l, IslandPaletteOwner as ln, BlurEvent as lt, computeEnterLeave as m, IslandSizeOwner as mn, Decoration as mt, HitRegistryContext as n, IslandInputEvent as nn, ConsoleEntry as nt, HitRegion as o, IslandMouseEvent as on, parseMouseSequence as ot, checkDoubleClick as p, IslandSignalsOwner as pn, CustomEvent as pt, CreateModesOptions as q, parseHotkey as qt, useHitRegion as r, IslandInputOwner as rn, ParseMouseOptions as rt, HitRegistry as s, IslandNodeState as sn, AgNode as st, BoundTerm as t, IslandHydrate as tn, FrameCell as tt, resetHitRegionIdCounter as u, IslandPalettePolicy as un, BoxProps as ut, createWheelEvent as v, ViewportRef as vn, InteractiveState as vt, FocusChangeCallback as w, SignalEvent as wt, processMouseEvent as x, Placement as xt, dispatchMouseEvent as y, KeyEvent$1 as yt, SignalName as z, InputHandler as zt };
4640
- //# sourceMappingURL=bound-term-0sPrrzH1.d.mts.map
5040
+ export { bufferToHTML as $, InputHandler as $t, SignalOnOptions as A, IslandSignalsOwner as An, Placement as At, Modes as B, SilveryMouseEvent as Bt, createTerm as C, IslandMouseEvent as Cn, Decoration as Ct, createConsole as D, IslandPalettePolicy as Dn, InteractiveState as Dt, ConsoleStats as E, IslandPaletteOwner as En, FocusEvent$1 as Et, InputOwnerOptions as F, ViewportProps as Fn, TextProps as Ft, NotificationRequest as G, FocusEventProps as Gt, NotificationAction as H, LayoutNode as Ht, createInputOwner as I, ViewportRect as In, TextTruncateHook as It, NotificationUrgency as J, createFocusEvent as Jt, NotificationTarget as K, SilveryFocusEvent as Kt, CreateModesOptions as L, ViewportRef as Ln, TextTruncateResult as Lt, Signals as M, CellBuffer as Mn, ResizeEvent as Mt, createSignals as N, ForeignSource as Nn, SignalEvent as Nt, CreateSignalsOptions as O, IslandProtocolModes as On, KeyEvent$1 as Ot, InputOwner as P, ViewportPalette as Pn, TextMeasure as Pt, UnderlineStyle as Q, CODE_TO_KEY as Qt, KittyFlags as R, UserSelect as Rt, Term as S, IslandModesOwner as Sn, CustomEvent as St, ConsoleCaptureOptions as T, IslandOutputOwner as Tn, EventSource as Tt, NotificationActivation as U, MeasureFunc as Ut, createModes as V, SilveryWheelEvent as Vt, NotificationDelivery as W, MeasureMode as Wt, Style as X, dispatchFocusEvent as Xt, Cell as Y, createKeyEvent as Yt, TerminalBuffer as Z, dispatchKeyEvent as Zt, BoundTerm as _, IslandHandle as _n, BlurEvent as _t, createDoubleClickState as a, keyToKittyAnsi as an, ParseMouseOptions as at, term as b, IslandInputOwner as bn, CollisionStrategy as bt, createWheelEvent as c, matchHotkey as cn, parseMouseSequence as ct, processMouseEvent as d, parseKeypress as dn, FocusManagerOptions as dt, Key as en, bufferToStyledText as et, HitRegion as f, IslandCapabilities as fn, FocusOrigin as ft, resetHitRegionIdCounter as g, IslandGuest as gn, AgNodeType as gt, Z_INDEX as h, IslandCursorState as hn, AgNode as ht, computeEnterLeave as i, keyToAnsi as in, ConsoleEntry as it, SignalUnregister as j, IslandSizeOwner as jn, Rect as jt, SignalName as k, IslandSignal as kn, MouseEvent as kt, dispatchMouseEvent as l, parseHotkey as ln, FocusChangeCallback as lt, HitTarget as m, IslandContext as mn, createFocusManager as mt, MouseEventProcessorState as n, ParsedKeypress as nn, FrameCell as nt, createMouseEvent as o, keyToModifiers as on, ParsedMouse as ot, HitRegistry as p, IslandCommandPrefix as pn, FocusSnapshot as pt, NotificationUnsupportedReason as q, SilveryKeyEvent as qt, checkDoubleClick as r, emptyKey as rn, TextFrame as rt, createMouseEventProcessor as s, keyToName as sn, isMouseSequence as st, MouseEventProcessorOptions as t, ParsedHotkey as tn, bufferToText as tt, hitTest as u, parseKey as un, FocusManager as ut, SelectionRange as v, IslandHydrate as vn, BoxProps as vt, Console as w, IslandNodeState as wn, Event as wt, StyleChain as x, IslandKeyEvent as xn, CursorShape as xt, TerminalSelectionState as y, IslandInputEvent as yn, Cell$1 as yt, ModeName as z, MouseEventProps as zt };
5041
+ //# sourceMappingURL=mouse-events-B2z5tbsL.d.mts.map