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.
- package/README.md +1 -1
- package/dist/{Text-Lq0dmj8-.mjs → Text-Ci6UCSTL.mjs} +46 -48
- package/dist/Text-Ci6UCSTL.mjs.map +1 -0
- package/dist/{render-string-DkQacASz.mjs → ag-q9lRlKlt.mjs} +5322 -4259
- package/dist/ag-q9lRlKlt.mjs.map +1 -0
- package/dist/{animation-ZMN2_XKv.mjs → animation-CZ4x2R7C.mjs} +1 -1
- package/dist/{animation-ZMN2_XKv.mjs.map → animation-CZ4x2R7C.mjs.map} +1 -1
- package/dist/{ansi-D1KQMAbf.mjs → ansi-CLmIMnop.mjs} +1 -1
- package/dist/{ansi-D1KQMAbf.mjs.map → ansi-CLmIMnop.mjs.map} +1 -1
- package/dist/{ansi-2Xn0yatP.d.mts → ansi-zmNzgkPB.d.mts} +1 -1
- package/dist/{ansi-2Xn0yatP.d.mts.map → ansi-zmNzgkPB.d.mts.map} +1 -1
- package/dist/{backend-B-WYLUib.mjs → backend-DSiSIc-h.mjs} +2 -2
- package/dist/{backend-B-WYLUib.mjs.map → backend-DSiSIc-h.mjs.map} +1 -1
- package/dist/chain-bridge-CkYcMxlq.mjs +4149 -0
- package/dist/chain-bridge-CkYcMxlq.mjs.map +1 -0
- package/dist/{chunk-BSw8zbkd.mjs → chunk-BEJ448es.mjs} +1 -3
- package/dist/cli-VNqUKlXw.mjs +4 -0
- package/dist/{context-BU5LkkIy.mjs → context-CEhuD1R_.mjs} +1 -1
- package/dist/{context-BU5LkkIy.mjs.map → context-CEhuD1R_.mjs.map} +1 -1
- package/dist/devtools-BF4IMumr.mjs +2 -0
- package/dist/{devtools-DcQjgyjL.mjs → devtools-td2AjFwc.mjs} +5 -5
- package/dist/{devtools-DcQjgyjL.mjs.map → devtools-td2AjFwc.mjs.map} +1 -1
- package/dist/{easing-BI-ASGMO.d.mts → easing-C5MrdO7V.d.mts} +1 -1
- package/dist/{easing-BI-ASGMO.d.mts.map → easing-C5MrdO7V.d.mts.map} +1 -1
- package/dist/{eta-CJlGH06n.mjs → eta-BwYWEjfS.mjs} +1 -1
- package/dist/{eta-CJlGH06n.mjs.map → eta-BwYWEjfS.mjs.map} +1 -1
- package/dist/{flexily-zero-adapter-C4lW_Ov5.mjs → flexily-zero-adapter-DktX3HsX.mjs} +1 -1
- package/dist/{flexily-zero-adapter-C3Vj0fPt.mjs → flexily-zero-adapter-VoBGHG14.mjs} +1 -1
- package/dist/{flexily-zero-adapter-C3Vj0fPt.mjs.map → flexily-zero-adapter-VoBGHG14.mjs.map} +1 -1
- package/dist/hit-registry-D_nxOivS.d.mts +71 -0
- package/dist/hit-registry-D_nxOivS.d.mts.map +1 -0
- package/dist/{UPNG-DosRPdF4.mjs → image-CIF75xMr.mjs} +891 -6
- package/dist/image-CIF75xMr.mjs.map +1 -0
- package/dist/{index-CSQf13CI.d.mts → index-377zdPLP.d.mts} +35 -12
- package/dist/index-377zdPLP.d.mts.map +1 -0
- package/dist/{index-Cl9KKjQ_.d.mts → index-BcSr0RAQ.d.mts} +8670 -10659
- package/dist/index-BcSr0RAQ.d.mts.map +1 -0
- package/dist/{index-XbNrPhWl.d.mts → index-DLnpxDAm.d.mts} +2 -2
- package/dist/{index-XbNrPhWl.d.mts.map → index-DLnpxDAm.d.mts.map} +1 -1
- package/dist/{index-BUMxS65f.d.mts → index-DlNmckTq.d.mts} +2 -2
- package/dist/{index-BUMxS65f.d.mts.map → index-DlNmckTq.d.mts.map} +1 -1
- package/dist/index.d.mts +12 -8
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +18 -15
- package/dist/index.mjs.map +1 -1
- package/dist/{layout-engine-C2px0RJE.mjs → layout-engine-BgR58vL0.mjs} +3 -3
- package/dist/{layout-engine-C2px0RJE.mjs.map → layout-engine-BgR58vL0.mjs.map} +1 -1
- package/dist/{layout-engine-C07LEXWT.mjs → layout-engine-DNjTha8f.mjs} +1 -1
- package/dist/{layout-signals-Cnw6xk8Q.mjs → layout-signals-CGYbHmxy.mjs} +146 -23
- package/dist/layout-signals-CGYbHmxy.mjs.map +1 -0
- package/dist/{bound-term-0sPrrzH1.d.mts → mouse-events-B2z5tbsL.d.mts} +780 -379
- package/dist/mouse-events-B2z5tbsL.d.mts.map +1 -0
- package/dist/{mouse-events-Dki3ISIp.mjs → mouse-events-WQ2h-uqG.mjs} +45 -10
- package/dist/mouse-events-WQ2h-uqG.mjs.map +1 -0
- package/dist/{multi-progress-DHZ2xUT2.d.mts → multi-progress-BaEFfHKP.d.mts} +2 -2
- package/dist/{multi-progress-DHZ2xUT2.d.mts.map → multi-progress-BaEFfHKP.d.mts.map} +1 -1
- package/dist/{multi-progress-CIRjrzma.mjs → multi-progress-zCWHEm9P.mjs} +3 -3
- package/dist/{multi-progress-CIRjrzma.mjs.map → multi-progress-zCWHEm9P.mjs.map} +1 -1
- package/dist/{node-CjM5Rt-M.mjs → node-CJ3J_rW-.mjs} +1 -1
- package/dist/{node-CjM5Rt-M.mjs.map → node-CJ3J_rW-.mjs.map} +1 -1
- package/dist/{progress-DB_Xo071.mjs → progress-6vJ7nxUg.mjs} +4 -4
- package/dist/{progress-DB_Xo071.mjs.map → progress-6vJ7nxUg.mjs.map} +1 -1
- package/dist/{progress-bar-oJwq22CR.mjs → progress-bar-BlFNsZL8.mjs} +4 -4
- package/dist/{progress-bar-oJwq22CR.mjs.map → progress-bar-BlFNsZL8.mjs.map} +1 -1
- package/dist/{reconciler-DldIJB93.mjs → reconciler--_-biN23.mjs} +190 -134
- package/dist/reconciler--_-biN23.mjs.map +1 -0
- package/dist/{render-string-BcoCpjCB.mjs → render-string-DaghHpLN.mjs} +1 -1
- package/dist/render-string-DtHZP0cU.mjs +215 -0
- package/dist/render-string-DtHZP0cU.mjs.map +1 -0
- package/dist/runtime.d.mts +4 -3
- package/dist/runtime.mjs +4 -3
- package/dist/schemes-DWQPxXAi.mjs +2516 -0
- package/dist/{schemes-JjNp4aSl.mjs.map → schemes-DWQPxXAi.mjs.map} +1 -1
- package/dist/{spinner-D9lrHr8s.mjs → spinner-B50hILqx.mjs} +19 -4
- package/dist/{spinner-D9lrHr8s.mjs.map → spinner-B50hILqx.mjs.map} +1 -1
- package/dist/{spinner-CZINHpkV.d.mts → spinner-DN10UfF0.d.mts} +2 -2
- package/dist/{spinner-CZINHpkV.d.mts.map → spinner-DN10UfF0.d.mts.map} +1 -1
- package/dist/{src-BNTToU7l.mjs → src-B8lf1kiR.mjs} +1507 -1166
- package/dist/src-B8lf1kiR.mjs.map +1 -0
- package/dist/{src-5w9QR6_8.mjs → src-BOLdi3WG.mjs} +105 -237
- package/dist/src-BOLdi3WG.mjs.map +1 -0
- package/dist/{src-BR4xNwdG.mjs → src-BXeTHHlL.mjs} +20240 -25437
- package/dist/src-BXeTHHlL.mjs.map +1 -0
- package/dist/{src-DKp-_OFG.mjs → src-BqeBFB3X.mjs} +90 -47
- package/dist/src-BqeBFB3X.mjs.map +1 -0
- package/dist/src-DbqcSrhy.mjs +3901 -0
- package/dist/src-DbqcSrhy.mjs.map +1 -0
- package/dist/{steps-Bp2uNqnn.d.mts → steps-B2kBmFpb.d.mts} +1 -1
- package/dist/{steps-Bp2uNqnn.d.mts.map → steps-B2kBmFpb.d.mts.map} +1 -1
- package/dist/{svg-Cz0UXcDj.mjs → svg-NmV9dgB9.mjs} +1 -1
- package/dist/{svg-Cz0UXcDj.mjs.map → svg-NmV9dgB9.mjs.map} +1 -1
- package/dist/{svg-g1D6ErwR.d.mts → svg-VUr78l5d.d.mts} +1 -1
- package/dist/{svg-g1D6ErwR.d.mts.map → svg-VUr78l5d.d.mts.map} +1 -1
- package/dist/term.d.mts +2 -2
- package/dist/term.mjs +3 -8
- package/dist/test.d.mts +673 -0
- package/dist/test.d.mts.map +1 -0
- package/dist/test.mjs +2829 -0
- package/dist/test.mjs.map +1 -0
- package/dist/theme.d.mts +2 -2
- package/dist/theme.d.mts.map +1 -1
- package/dist/theme.mjs +3 -8
- package/dist/{types-kt_fKR37.d.mts → types-D_E0FbqA.d.mts} +1 -1
- package/dist/{types-kt_fKR37.d.mts.map → types-D_E0FbqA.d.mts.map} +1 -1
- package/dist/ui/animation.d.mts +2 -2
- package/dist/ui/animation.mjs +1 -1
- package/dist/ui/ansi.d.mts +1 -1
- package/dist/ui/ansi.mjs +1 -1
- package/dist/ui/cli.d.mts +3 -3
- package/dist/ui/cli.mjs +5 -5
- package/dist/ui/image.d.mts +1 -1
- package/dist/ui/image.mjs +1 -1
- package/dist/ui/progress.d.mts +4 -4
- package/dist/ui/progress.mjs +4 -4
- package/dist/ui/react.d.mts +1 -1
- package/dist/ui/react.mjs +2 -2
- package/dist/ui/recording-chrome-react.d.mts +1 -1
- package/dist/ui/recording-chrome-react.mjs +2 -2
- package/dist/ui/recording-chrome.d.mts +1 -1
- package/dist/ui/recording-chrome.mjs +1 -1
- package/dist/ui/utils.mjs +1 -1
- package/dist/ui/wrappers.d.mts +2 -2
- package/dist/ui/wrappers.mjs +1 -1
- package/dist/ui.d.mts +6 -6
- package/dist/ui.mjs +7 -7
- package/dist/unicode-CxyxVGmB.mjs +11077 -0
- package/dist/unicode-CxyxVGmB.mjs.map +1 -0
- package/dist/{useLatest-DRDDVwjh.d.mts → useLatest-UOvWy0ZW.d.mts} +2 -2
- package/dist/{useLatest-DRDDVwjh.d.mts.map → useLatest-UOvWy0ZW.d.mts.map} +1 -1
- package/dist/useLayout-D5cE8OCI.mjs +424 -0
- package/dist/useLayout-D5cE8OCI.mjs.map +1 -0
- package/dist/{with-text-input-YeohVLeo.d.mts → with-text-input-DLoSCBrm.d.mts} +3 -3
- package/dist/{with-text-input-YeohVLeo.d.mts.map → with-text-input-DLoSCBrm.d.mts.map} +1 -1
- package/dist/wrap-measurer-registration-IV2HtcCd.d.mts +3106 -0
- package/dist/wrap-measurer-registration-IV2HtcCd.d.mts.map +1 -0
- package/dist/{wrapper-C70ATkVv.mjs → wrapper-CD29afOs.mjs} +59 -17
- package/dist/wrapper-CD29afOs.mjs.map +1 -0
- package/dist/{wrappers-BCUYITrY.mjs → wrappers-CInBJm44.mjs} +18 -8
- package/dist/wrappers-CInBJm44.mjs.map +1 -0
- package/dist/{yoga-adapter-BnZX1PAY.mjs → yoga-adapter-9uab5Qn-.mjs} +2 -2
- package/dist/{yoga-adapter-BnZX1PAY.mjs.map → yoga-adapter-9uab5Qn-.mjs.map} +1 -1
- package/dist/yoga-adapter-yqTl1aXK.mjs +2 -0
- package/package.json +59 -14
- package/dist/Text-Lq0dmj8-.mjs.map +0 -1
- package/dist/UPNG-Bo33r8rA.mjs +0 -3
- package/dist/UPNG-DosRPdF4.mjs.map +0 -1
- package/dist/__vite-browser-external-2447137e-D_JM6skp.mjs +0 -6
- package/dist/__vite-browser-external-2447137e-D_JM6skp.mjs.map +0 -1
- package/dist/ansi-yC4RyBNY.mjs +0 -22441
- package/dist/ansi-yC4RyBNY.mjs.map +0 -1
- package/dist/apng-CR08rIaH.mjs +0 -58
- package/dist/apng-CR08rIaH.mjs.map +0 -1
- package/dist/apng-DaHfVaVI.mjs +0 -3
- package/dist/assets/resvgjs.darwin-arm64-BtufyGW1.node +0 -0
- package/dist/assets/skia.darwin-arm64-DQs5sT6N.node +0 -0
- package/dist/backends-CUtan80W.mjs +0 -3
- package/dist/backends-DIVYzKqd.mjs +0 -1083
- package/dist/backends-DIVYzKqd.mjs.map +0 -1
- package/dist/bound-term-0sPrrzH1.d.mts.map +0 -1
- package/dist/canvas-1v7dPT-_.mjs +0 -3
- package/dist/canvas-CSuPOMNt.mjs +0 -1442
- package/dist/canvas-CSuPOMNt.mjs.map +0 -1
- package/dist/cli-dvo0r2fs.mjs +0 -4
- package/dist/compare-CQodSH4G.mjs +0 -376
- package/dist/compare-CQodSH4G.mjs.map +0 -1
- package/dist/compare-DHlcxEYA.mjs +0 -3
- package/dist/devtools-CJdt5H0X.mjs +0 -2
- package/dist/fonts-BFmhXDv7.mjs +0 -88
- package/dist/fonts-BFmhXDv7.mjs.map +0 -1
- package/dist/gif-C_AjaT9d.mjs +0 -188
- package/dist/gif-C_AjaT9d.mjs.map +0 -1
- package/dist/gif-DaC4XrxA.mjs +0 -3
- package/dist/gifenc-BOUT-KFB.mjs +0 -730
- package/dist/gifenc-BOUT-KFB.mjs.map +0 -1
- package/dist/image-C2Birh2x.mjs +0 -1252
- package/dist/image-C2Birh2x.mjs.map +0 -1
- package/dist/index-CSQf13CI.d.mts.map +0 -1
- package/dist/index-Cl9KKjQ_.d.mts.map +0 -1
- package/dist/key-mapping-CS-YD_cD.mjs +0 -132
- package/dist/key-mapping-CS-YD_cD.mjs.map +0 -1
- package/dist/key-mapping-Yn-Jgrij.mjs +0 -3
- package/dist/layout-signals-Cnw6xk8Q.mjs.map +0 -1
- package/dist/mouse-events-Dki3ISIp.mjs.map +0 -1
- package/dist/playwright-D5YiZcNS.mjs +0 -76397
- package/dist/playwright-D5YiZcNS.mjs.map +0 -1
- package/dist/png-codec-Dp84742B.mjs +0 -36
- package/dist/png-codec-Dp84742B.mjs.map +0 -1
- package/dist/png-codec-QwOtJ8Zs.mjs +0 -3
- package/dist/rasterizer-BRXrDdWx.mjs +0 -3
- package/dist/rasterizer-CpEhJvdR.mjs +0 -296
- package/dist/rasterizer-CpEhJvdR.mjs.map +0 -1
- package/dist/reconciler-DldIJB93.mjs.map +0 -1
- package/dist/render-string-DkQacASz.mjs.map +0 -1
- package/dist/resvg-js-DkOndZI3.mjs +0 -203
- package/dist/resvg-js-DkOndZI3.mjs.map +0 -1
- package/dist/schemes-JjNp4aSl.mjs +0 -2611
- package/dist/src-5w9QR6_8.mjs.map +0 -1
- package/dist/src-BNTToU7l.mjs.map +0 -1
- package/dist/src-BR4xNwdG.mjs.map +0 -1
- package/dist/src-DKp-_OFG.mjs.map +0 -1
- package/dist/src-bt8wSrfJ.mjs +0 -258
- package/dist/src-bt8wSrfJ.mjs.map +0 -1
- package/dist/src-e33Y6kNJ.mjs +0 -3
- package/dist/src-iDwu25UD.mjs +0 -1814
- package/dist/src-iDwu25UD.mjs.map +0 -1
- package/dist/svg-15lZZzxq.mjs +0 -486
- package/dist/svg-15lZZzxq.mjs.map +0 -1
- package/dist/svg-DY72a4HK.mjs +0 -3
- package/dist/term.mjs.map +0 -1
- package/dist/theme.mjs.map +0 -1
- package/dist/ui/display.d.mts +0 -35
- package/dist/ui/display.d.mts.map +0 -1
- package/dist/ui/display.mjs +0 -123
- package/dist/ui/display.mjs.map +0 -1
- package/dist/ui/input.d.mts +0 -184
- package/dist/ui/input.d.mts.map +0 -1
- package/dist/ui/input.mjs +0 -285
- package/dist/ui/input.mjs.map +0 -1
- package/dist/wrapper-C70ATkVv.mjs.map +0 -1
- package/dist/wrappers-BCUYITrY.mjs.map +0 -1
- package/dist/yoga-adapter-DxgsQ_gg.mjs +0 -2
- package/dist/zipBundle-3nqeDRtm.mjs +0 -3
- package/dist/zipBundle-VNAYFmqJ.mjs +0 -2003
- package/dist/zipBundle-VNAYFmqJ.mjs.map +0 -1
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { M as RGB$1, N as
|
|
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
|
|
811
|
+
/** Current Silvery layout-space position of the pointer */
|
|
756
812
|
position: {
|
|
757
813
|
x: number;
|
|
758
814
|
y: number;
|
|
759
815
|
};
|
|
760
|
-
/** The
|
|
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
|
|
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
|
|
790
|
-
* '#', opt+e inserts '´', and IME
|
|
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:
|
|
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)
|
|
1396
|
+
/** Vertical scroll: -1 (up), +1 (down), or 0 for a pure-horizontal wheel */
|
|
1289
1397
|
deltaY: number;
|
|
1290
|
-
/**
|
|
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.
|
|
1802
|
-
*
|
|
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
|
|
1872
|
-
* `
|
|
1873
|
-
*
|
|
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
|
-
/**
|
|
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
|
|
3369
|
-
* can take over seamlessly.
|
|
3943
|
+
* set for a caller-managed handoff.
|
|
3370
3944
|
*
|
|
3371
|
-
*
|
|
3372
|
-
*
|
|
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
|
|
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/
|
|
4106
|
-
|
|
4107
|
-
|
|
4108
|
-
|
|
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
|
|
4125
|
-
|
|
4126
|
-
|
|
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/
|
|
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
|
-
*
|
|
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
|
|
4367
|
-
|
|
4368
|
-
|
|
4369
|
-
|
|
4370
|
-
|
|
4371
|
-
|
|
4372
|
-
|
|
4373
|
-
|
|
4374
|
-
|
|
4375
|
-
|
|
4376
|
-
/**
|
|
4377
|
-
|
|
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/
|
|
4874
|
+
//#region packages/ag-term/src/mouse-events.d.ts
|
|
4556
4875
|
/**
|
|
4557
|
-
*
|
|
4558
|
-
*
|
|
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
|
|
4884
|
+
declare function createMouseEvent(type: SilveryMouseEvent["type"], x: number, y: number, target: AgNode, parsed: ParsedMouse, keyboardMods?: KeyboardModifierState): SilveryMouseEvent;
|
|
4561
4885
|
/**
|
|
4562
|
-
*
|
|
4563
|
-
*
|
|
4564
|
-
* @returns The HitRegistry instance, or null if not in a HitRegistryContext
|
|
4886
|
+
* Create a synthetic wheel event.
|
|
4565
4887
|
*/
|
|
4566
|
-
declare function
|
|
4888
|
+
declare function createWheelEvent(x: number, y: number, target: AgNode, parsed: ParsedMouse, keyboardMods?: KeyboardModifierState): SilveryWheelEvent;
|
|
4567
4889
|
/**
|
|
4568
|
-
*
|
|
4890
|
+
* Tree-based hit test: find the deepest node whose scrollRect contains (x, y).
|
|
4569
4891
|
*
|
|
4570
|
-
*
|
|
4571
|
-
*
|
|
4892
|
+
* Uses reverse child order (last sibling wins = highest z-order, like DOM).
|
|
4893
|
+
* Respects overflow:hidden clipping and pointerEvents="none".
|
|
4572
4894
|
*
|
|
4573
|
-
*
|
|
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
|
-
*
|
|
4579
|
-
*
|
|
4580
|
-
*
|
|
4581
|
-
*
|
|
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
|
-
*
|
|
4584
|
-
*
|
|
4585
|
-
*
|
|
4586
|
-
*
|
|
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
|
-
*
|
|
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
|
|
4913
|
+
declare function hitTest(node: AgNode, x: number, y: number): AgNode | null;
|
|
4594
4914
|
/**
|
|
4595
|
-
*
|
|
4915
|
+
* Dispatch a mouse event through the render tree with DOM-style bubbling.
|
|
4596
4916
|
*
|
|
4597
|
-
*
|
|
4598
|
-
*
|
|
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
|
-
*
|
|
4601
|
-
*
|
|
4602
|
-
*
|
|
4603
|
-
*
|
|
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
|
-
*
|
|
4606
|
-
|
|
4607
|
-
|
|
4608
|
-
|
|
4609
|
-
|
|
4610
|
-
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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
|
|
4620
|
-
|
|
4621
|
-
|
|
4960
|
+
declare function computeEnterLeave(prevPath: AgNode[], nextPath: AgNode[]): {
|
|
4961
|
+
entered: AgNode[];
|
|
4962
|
+
left: AgNode[];
|
|
4963
|
+
};
|
|
4622
4964
|
/**
|
|
4623
|
-
*
|
|
4965
|
+
* Options for creating a mouse event processor.
|
|
4624
4966
|
*/
|
|
4625
|
-
interface
|
|
4626
|
-
/**
|
|
4627
|
-
|
|
4628
|
-
|
|
4629
|
-
|
|
4630
|
-
|
|
4631
|
-
|
|
4632
|
-
|
|
4633
|
-
|
|
4634
|
-
|
|
4635
|
-
|
|
4636
|
-
|
|
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 {
|
|
4640
|
-
//# sourceMappingURL=
|
|
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
|