@silo-code/sdk 0.51.0 → 0.52.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/dist/index.d.ts CHANGED
@@ -6,9 +6,9 @@
6
6
  *
7
7
  * **What's here:** the types-first extension contract (see `types.ts`) plus a
8
8
  * small set of blessed runtime helpers (`Tooltip`, the modal design-system
9
- * kit, `useFocusGroup`, `useServiceState`, `DND_MIME`, `PathDeniedError`,
10
- * `NetworkError`). The SDK peer-depends on React 19; changes to the runtime
11
- * helpers can be breaking even when the types are unchanged.
9
+ * kit, `useFocusGroup`, `usePanelEntryFocus`, `useServiceState`, `DND_MIME`,
10
+ * `PathDeniedError`, `NetworkError`). The SDK peer-depends on React 19; changes
11
+ * to the runtime helpers can be breaking even when the types are unchanged.
12
12
  *
13
13
  * This is also the entry point the API-reference generator (TypeDoc) reads, so
14
14
  * the published reference is exactly this surface — no more, no less.
@@ -84,5 +84,8 @@ export { useServiceState } from "./use-service-state.js";
84
84
  export type { ReactiveService } from "./use-service-state.js";
85
85
  export { useFocusGroup, focusGroupNextIndex } from "./use-focus-group.js";
86
86
  export type { FocusGroup, FocusGroupOptions, FocusGroupContainerProps, FocusGroupItemProps, FocusGroupOrientation, FocusGroupNavQuery, } from "./use-focus-group.js";
87
+ export { usePanelEntryFocus } from "./use-panel-entry-focus.js";
88
+ export type { PanelEntryFocusTarget } from "./use-panel-entry-focus.js";
87
89
  export { setActiveInlineEditCancel, yieldEscapeToInlineEdit, } from "./inline-edit-controller.js";
90
+ export { retryFocus } from "./use-panel-entry-focus.js";
88
91
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -6,9 +6,9 @@
6
6
  *
7
7
  * **What's here:** the types-first extension contract (see `types.ts`) plus a
8
8
  * small set of blessed runtime helpers (`Tooltip`, the modal design-system
9
- * kit, `useFocusGroup`, `useServiceState`, `DND_MIME`, `PathDeniedError`,
10
- * `NetworkError`). The SDK peer-depends on React 19; changes to the runtime
11
- * helpers can be breaking even when the types are unchanged.
9
+ * kit, `useFocusGroup`, `usePanelEntryFocus`, `useServiceState`, `DND_MIME`,
10
+ * `PathDeniedError`, `NetworkError`). The SDK peer-depends on React 19; changes
11
+ * to the runtime helpers can be breaking even when the types are unchanged.
12
12
  *
13
13
  * This is also the entry point the API-reference generator (TypeDoc) reads, so
14
14
  * the published reference is exactly this surface — no more, no less.
@@ -61,8 +61,15 @@ export { useServiceState } from "./use-service-state.js";
61
61
  // `focusGroupNextIndex` helper is the pure roving-index core for widgets that
62
62
  // can't use the focus-driven hook (e.g. menus driven by a document listener).
63
63
  export { useFocusGroup, focusGroupNextIndex } from "./use-focus-group.js";
64
- // Host/InlineEdit coordination for InlineEdit's two-stage Escape (RFC 0016).
64
+ // Entry focus for a dock panel (RFC 0049): both entry signals + the
65
+ // `isActive`-guarded frame retry that wins dockview's focus shuffle, in one
66
+ // call. The one sanctioned way for panel content to take focus on entry.
67
+ export { usePanelEntryFocus } from "./use-panel-entry-focus.js";
68
+ // Host/InlineEdit coordination for InlineEdit's two-stage Escape (RFC 0016),
69
+ // and the raw focus retry behind `usePanelEntryFocus` for the non-React
70
+ // callers that can't use the hook (RFC 0049).
65
71
  // @internal — host-only plumbing, not part of the documented reference;
66
72
  // extension authors never call these directly.
67
73
  export { setActiveInlineEditCancel, yieldEscapeToInlineEdit, } from "./inline-edit-controller.js";
74
+ export { retryFocus } from "./use-panel-entry-focus.js";
68
75
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AA2JH,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAiChD,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AA8BlE,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAyBzC,sEAAsE;AACtE,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAkCjD,8EAA8E;AAC9E,8EAA8E;AAC9E,6DAA6D;AAC7D,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAE9B,yEAAyE;AACzE,iFAAiF;AACjF,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,4EAA4E;AAC5E,qDAAqD;AACrD,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAElC,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE1C,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE1C,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAChC,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE1C,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAE9C,4DAA4D;AAC5D,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAEhD,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAExC,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAEvC,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAEhC,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE1C,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE1C,wEAAwE;AACxE,iFAAiF;AACjF,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAEtD,8EAA8E;AAC9E,4EAA4E;AAC5E,8EAA8E;AAC9E,8EAA8E;AAC9E,OAAO,EAAE,aAAa,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAUvE,6EAA6E;AAC7E,wEAAwE;AACxE,+CAA+C;AAC/C,OAAO,EACL,yBAAyB,EACzB,uBAAuB,GACxB,MAAM,0BAA0B,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AA2JH,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAiChD,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AA8BlE,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAyBzC,sEAAsE;AACtE,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAkCjD,8EAA8E;AAC9E,8EAA8E;AAC9E,6DAA6D;AAC7D,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAE9B,yEAAyE;AACzE,iFAAiF;AACjF,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,4EAA4E;AAC5E,qDAAqD;AACrD,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAElC,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE1C,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE1C,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAChC,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE1C,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAE9C,4DAA4D;AAC5D,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAEhD,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAExC,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAEvC,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAEhC,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE1C,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE1C,wEAAwE;AACxE,iFAAiF;AACjF,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAEtD,8EAA8E;AAC9E,4EAA4E;AAC5E,8EAA8E;AAC9E,8EAA8E;AAC9E,OAAO,EAAE,aAAa,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAUvE,oEAAoE;AACpE,4EAA4E;AAC5E,yEAAyE;AACzE,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAG7D,6EAA6E;AAC7E,wEAAwE;AACxE,8CAA8C;AAC9C,wEAAwE;AACxE,+CAA+C;AAC/C,OAAO,EACL,yBAAyB,EACzB,uBAAuB,GACxB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC"}
package/dist/types.d.ts CHANGED
@@ -85,6 +85,37 @@ export interface DockPanelApi {
85
85
  onDidActiveChange(listener: (event: {
86
86
  readonly isActive: boolean;
87
87
  }) => void): Disposable;
88
+ /**
89
+ * Subscribe to the user asking, by gesture, for keyboard focus in this
90
+ * panel — fired on every click of its tab, including one that leaves
91
+ * {@link DockPanelApi.isActive | isActive} unchanged because the tab was
92
+ * already active.
93
+ *
94
+ * That already-active case is why the event exists: it has no other signal.
95
+ * {@link DockPanelApi.onDidActiveChange | onDidActiveChange} only fires on a
96
+ * real transition, so clicking back into an already-active tab from
97
+ * elsewhere (a side panel, the status bar) is otherwise silent even though
98
+ * the user's intent — "put keyboard focus here" — is identical to a genuine
99
+ * activation. A panel that drives its own entry focus from
100
+ * `onDidActiveChange` should drive it from this event too, guarded on
101
+ * `isActive`, so both paths land focus the same way.
102
+ *
103
+ * The name is the intent, but today exactly one gesture carries it:
104
+ *
105
+ * - **Fires** on a primary click of this panel's tab, whether or not the
106
+ * panel was already the active one.
107
+ * - **Does not fire** for activation from anywhere else —
108
+ * {@link DockPanelApi.setActive | setActive}, a keybinding, a command or
109
+ * command-palette jump, or the host restoring a saved layout. Those change
110
+ * which panel is active, so they surface as `onDidActiveChange` instead;
111
+ * none of them reaches this event.
112
+ * - **Does not fire** for a click inside the panel's own content (focus
113
+ * there is yours to manage), the tab's close button, or a middle-click
114
+ * close.
115
+ *
116
+ * Returns a {@link Disposable} that cancels the subscription.
117
+ */
118
+ onDidRequestFocus(listener: () => void): Disposable;
88
119
  /**
89
120
  * `true` while this panel is visible — its tab is the selected one in its
90
121
  * group. Distinct from {@link DockPanelApi.isActive | isActive}: with split
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,122 @@
1
+ import type { DockPanelApi } from "./types.js";
2
+ /**
3
+ * Repeatedly call `focus()` on successive animation frames until `isFocused()`
4
+ * returns true, `stillWanted()` returns false, or `cap` frames have elapsed.
5
+ *
6
+ * `stillWanted` is **required**, and must express "this panel is still the one
7
+ * that should hold focus" — normally `() => api.isActive`, or the center
8
+ * dock's focus-intent token (`focusGen`). It is deliberately not optional: a
9
+ * retry loop without it keeps grabbing focus for its entire frame budget no
10
+ * matter what else happened meanwhile. That matters most on *mount*, because
11
+ * re-entering a workspace re-mounts its panels — so an unguarded mount-time
12
+ * grab in a background tab yanks focus away from the tab the user actually
13
+ * left active. And because DOM focus landing inside a dockview panel makes
14
+ * dockview mark that panel's group active
15
+ * (`contentContainer.onDidFocus → doSetGroupActive`), stealing focus silently
16
+ * changes the visible active tab too. That was symptom 1 in ADR 0034.
17
+ *
18
+ * Panel content should reach for {@link usePanelEntryFocus} instead, which
19
+ * supplies the guard and both entry subscriptions for you. This raw form is
20
+ * host/`core.*` plumbing for the non-React callers that can't.
21
+ *
22
+ * @internal
23
+ */
24
+ export declare function retryFocus(focus: () => void, isFocused: () => boolean, stillWanted: () => boolean, cap?: number): void;
25
+ /**
26
+ * The content {@link usePanelEntryFocus} drives — how to focus it, how to tell
27
+ * whether it already has focus, and optionally how to release it.
28
+ *
29
+ * All three are called through a latest-ref, so inline closures over props or
30
+ * state are always current; you never need to memoize them.
31
+ *
32
+ * @category Core Types
33
+ * @public
34
+ */
35
+ export interface PanelEntryFocusTarget {
36
+ /**
37
+ * Imperatively focus the panel's content — e.g. `() => inputRef.current?.focus()`
38
+ * or `() => editor.focus()`. Safe to make a no-op while the content isn't
39
+ * ready to take focus; the retry simply expires.
40
+ */
41
+ focus: () => void;
42
+ /**
43
+ * Whether the content holds DOM keyboard focus **right now**, so the retry
44
+ * can stop as soon as it lands instead of burning the whole frame budget.
45
+ *
46
+ * Read the live `document.activeElement` — e.g.
47
+ * `() => document.activeElement === inputRef.current`. Don't trust a
48
+ * library's own tracker flag (Monaco's `hasTextFocus()`, say): those go
49
+ * stale-true when a blur is dropped during dockview's show/hide shuffle,
50
+ * which stops the retry believing focus landed when it didn't.
51
+ */
52
+ isFocused: () => boolean;
53
+ /**
54
+ * Release the content's focus when the panel's tab is deactivated. Only
55
+ * needed for content that tracks its own focus state internally — a Monaco
56
+ * editor or an xterm terminal is kept alive (hidden) while its tab is
57
+ * inactive, and if its tracker stays stuck believing it has focus it will
58
+ * steal keystrokes meant for the tab you switched to. A plain input needs
59
+ * nothing here.
60
+ */
61
+ blur?: () => void;
62
+ }
63
+ /**
64
+ * Land keyboard focus in a dock panel's content whenever the user enters the
65
+ * panel, winning dockview's focus shuffle — and, symmetrically, release it when
66
+ * the panel's tab is deactivated.
67
+ *
68
+ * A panel that puts the cursor somewhere on entry (a chat composer, a search
69
+ * box, an editor) needs three things that are easy to get individually wrong,
70
+ * and this hook is all three in one call:
71
+ *
72
+ * 1. **Both entry signals.** {@link DockPanelApi.onDidActiveChange} covers real
73
+ * activations. {@link DockPanelApi.onDidRequestFocus} covers a click on a
74
+ * tab that was *already* active — dockview treats that as a complete no-op
75
+ * and fires no active-change event, even though it is the commonest way a
76
+ * user asks for the cursor back (they were typing in a side panel, clicked
77
+ * the status bar, then clicked your tab).
78
+ * 2. **A guard.** Focus is only ever taken while the panel is the active one.
79
+ * Mount is not "the user just created this panel" — re-entering a workspace
80
+ * re-mounts every panel in its dock — and DOM focus landing in a panel makes
81
+ * dockview activate its group, so an unguarded grab silently changes the
82
+ * visible tab (ADR 0034).
83
+ * 3. **A retry.** A single `focus()` loses dockview's shuffle, and rich content
84
+ * only accepts focus once its internal textarea is laid out. The hook
85
+ * retries across frames until focus lands, standing down if the panel stops
86
+ * being active or focus moves into an open context menu.
87
+ *
88
+ * ```tsx
89
+ * function AcmeChatPanel({ api }: DockPanelProps) {
90
+ * const input = useRef<HTMLTextAreaElement | null>(null);
91
+ *
92
+ * usePanelEntryFocus(api, {
93
+ * focus: () => input.current?.focus(),
94
+ * isFocused: () => document.activeElement === input.current,
95
+ * });
96
+ *
97
+ * return <textarea ref={input} />;
98
+ * }
99
+ * ```
100
+ *
101
+ * The returned function runs the same guarded retry on demand, for content that
102
+ * becomes focusable at a moment that is neither a mount nor an activation — a
103
+ * session finishing its connect, an editor finishing its own mount. It is
104
+ * referentially stable, so it is safe in a dependency array:
105
+ *
106
+ * ```tsx
107
+ * const focusComposer = usePanelEntryFocus(api, { focus, isFocused });
108
+ *
109
+ * useEffect(() => {
110
+ * if (ready) focusComposer();
111
+ * }, [ready, focusComposer]);
112
+ * ```
113
+ *
114
+ * @param api - The surrounding panel's api ({@link DockPanelProps.api}).
115
+ * @param target - How to focus, test, and release the panel's content.
116
+ * @returns A stable callback that runs the guarded focus retry on demand.
117
+ *
118
+ * @category Consumer Services
119
+ * @public
120
+ */
121
+ export declare function usePanelEntryFocus(api: DockPanelApi, target: PanelEntryFocusTarget): () => void;
122
+ //# sourceMappingURL=use-panel-entry-focus.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-panel-entry-focus.d.ts","sourceRoot":"","sources":["../src/use-panel-entry-focus.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAoC5C;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,UAAU,CACxB,KAAK,EAAE,MAAM,IAAI,EACjB,SAAS,EAAE,MAAM,OAAO,EACxB,WAAW,EAAE,MAAM,OAAO,EAC1B,GAAG,SAAc,GAChB,IAAI,CAoCN;AAED;;;;;;;;;GASG;AACH,MAAM,WAAW,qBAAqB;IACpC;;;;OAIG;IACH,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB;;;;;;;;;OASG;IACH,SAAS,EAAE,MAAM,OAAO,CAAC;IACzB;;;;;;;OAOG;IACH,IAAI,CAAC,EAAE,MAAM,IAAI,CAAC;CACnB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyDG;AACH,wBAAgB,kBAAkB,CAChC,GAAG,EAAE,YAAY,EACjB,MAAM,EAAE,qBAAqB,GAC5B,MAAM,IAAI,CAkCZ"}
@@ -0,0 +1,186 @@
1
+ import { useCallback, useEffect, useRef } from "react";
2
+ // Entry focus for a dock panel — landing the caret in the panel's content when
3
+ // the user enters it.
4
+ //
5
+ // A freshly-mounted or newly-activated dock panel does NOT reliably inherit DOM
6
+ // focus: dockview runs its own focus shuffle when panels mount/activate, and
7
+ // rich content (Monaco, xterm) only accepts focus once its internal textarea
8
+ // has been laid out with non-zero dimensions. A single `focus()` call loses
9
+ // these races, which is why a panel would otherwise need a second click before
10
+ // you can type. We retry across animation frames until the target actually
11
+ // reports focus, the panel is no longer the one we wanted to focus, or we hit a
12
+ // frame cap (~330ms) so we never loop forever when focus legitimately can't be
13
+ // grabbed (panel hidden, content disabled, etc.).
14
+ const DEFAULT_CAP = 20;
15
+ // Every menu implementation whose open state must suppress the retry: Silo's
16
+ // own menus (`ctx.ui.showMenu`, which renders `[data-silo-menu]` with
17
+ // `role="menu"`), a third-party menu that follows the same ARIA role, and
18
+ // Monaco's context menu (`.context-view` / `.monaco-menu`).
19
+ const MENU_SELECTOR = '[data-silo-menu], [role="menu"], .context-view, .monaco-menu';
20
+ /**
21
+ * Whether focus currently sits inside an open floating menu. Monaco renders its
22
+ * context menu into a shadow root, where `document.activeElement` resolves only
23
+ * to the open `shadow-root-host` and the menu nodes hang off its `shadowRoot` —
24
+ * hence the shadow peek, not just a light-DOM `closest`.
25
+ */
26
+ function focusInMenu(active) {
27
+ if (!active)
28
+ return false;
29
+ if (active.closest(MENU_SELECTOR))
30
+ return true;
31
+ return active.shadowRoot?.querySelector(MENU_SELECTOR) != null;
32
+ }
33
+ /**
34
+ * Repeatedly call `focus()` on successive animation frames until `isFocused()`
35
+ * returns true, `stillWanted()` returns false, or `cap` frames have elapsed.
36
+ *
37
+ * `stillWanted` is **required**, and must express "this panel is still the one
38
+ * that should hold focus" — normally `() => api.isActive`, or the center
39
+ * dock's focus-intent token (`focusGen`). It is deliberately not optional: a
40
+ * retry loop without it keeps grabbing focus for its entire frame budget no
41
+ * matter what else happened meanwhile. That matters most on *mount*, because
42
+ * re-entering a workspace re-mounts its panels — so an unguarded mount-time
43
+ * grab in a background tab yanks focus away from the tab the user actually
44
+ * left active. And because DOM focus landing inside a dockview panel makes
45
+ * dockview mark that panel's group active
46
+ * (`contentContainer.onDidFocus → doSetGroupActive`), stealing focus silently
47
+ * changes the visible active tab too. That was symptom 1 in ADR 0034.
48
+ *
49
+ * Panel content should reach for {@link usePanelEntryFocus} instead, which
50
+ * supplies the guard and both entry subscriptions for you. This raw form is
51
+ * host/`core.*` plumbing for the non-React callers that can't.
52
+ *
53
+ * @internal
54
+ */
55
+ export function retryFocus(focus, isFocused, stillWanted, cap = DEFAULT_CAP) {
56
+ let attempts = 0;
57
+ let landed = false;
58
+ const tick = () => {
59
+ // Bail before touching focus if we're no longer wanted — a newer focus
60
+ // intent superseded us (e.g. the user kept pressing the region-cycle chord).
61
+ // Checked here, not just after the grab below, so a stale retry can't yank
62
+ // focus back from the area the user actually moved to.
63
+ if (!stillWanted())
64
+ return;
65
+ attempts += 1;
66
+ if (isFocused()) {
67
+ landed = true;
68
+ }
69
+ else {
70
+ // Before focus first lands, grab aggressively each frame — Monaco/xterm
71
+ // only accept focus once their textarea is laid out, so early calls lose.
72
+ // After it has landed, only re-grab if focus fell to NOTHING (<body>/null):
73
+ // dockview's show/hide shuffle can bounce focus off the just-focused
74
+ // content a frame or two later (the "keystrokes dropped after a switch"
75
+ // symptom). We watch the full frame budget to catch that — but never yank
76
+ // focus away from another real element the user may have moved to.
77
+ const active = document.activeElement;
78
+ // Focus legitimately moved into an open context menu — don't yank it
79
+ // back, or the menu's focus-out dismiss fires and it flashes shut.
80
+ // Right-clicking an *inactive* panel activates it, which starts this
81
+ // retry; without the guard the per-frame `focus()` steals focus from the
82
+ // just-opened menu (the focused case never starts the retry, which is why
83
+ // the bug only shows when the panel was unfocused). End the loop: the
84
+ // menu's owner restores content focus itself once the menu closes.
85
+ if (focusInMenu(active))
86
+ return;
87
+ const lostToNothing = active === null || active === document.body;
88
+ if (!landed || lostToNothing)
89
+ focus();
90
+ }
91
+ if (attempts >= cap || !stillWanted())
92
+ return;
93
+ requestAnimationFrame(tick);
94
+ };
95
+ requestAnimationFrame(tick);
96
+ }
97
+ /**
98
+ * Land keyboard focus in a dock panel's content whenever the user enters the
99
+ * panel, winning dockview's focus shuffle — and, symmetrically, release it when
100
+ * the panel's tab is deactivated.
101
+ *
102
+ * A panel that puts the cursor somewhere on entry (a chat composer, a search
103
+ * box, an editor) needs three things that are easy to get individually wrong,
104
+ * and this hook is all three in one call:
105
+ *
106
+ * 1. **Both entry signals.** {@link DockPanelApi.onDidActiveChange} covers real
107
+ * activations. {@link DockPanelApi.onDidRequestFocus} covers a click on a
108
+ * tab that was *already* active — dockview treats that as a complete no-op
109
+ * and fires no active-change event, even though it is the commonest way a
110
+ * user asks for the cursor back (they were typing in a side panel, clicked
111
+ * the status bar, then clicked your tab).
112
+ * 2. **A guard.** Focus is only ever taken while the panel is the active one.
113
+ * Mount is not "the user just created this panel" — re-entering a workspace
114
+ * re-mounts every panel in its dock — and DOM focus landing in a panel makes
115
+ * dockview activate its group, so an unguarded grab silently changes the
116
+ * visible tab (ADR 0034).
117
+ * 3. **A retry.** A single `focus()` loses dockview's shuffle, and rich content
118
+ * only accepts focus once its internal textarea is laid out. The hook
119
+ * retries across frames until focus lands, standing down if the panel stops
120
+ * being active or focus moves into an open context menu.
121
+ *
122
+ * ```tsx
123
+ * function AcmeChatPanel({ api }: DockPanelProps) {
124
+ * const input = useRef<HTMLTextAreaElement | null>(null);
125
+ *
126
+ * usePanelEntryFocus(api, {
127
+ * focus: () => input.current?.focus(),
128
+ * isFocused: () => document.activeElement === input.current,
129
+ * });
130
+ *
131
+ * return <textarea ref={input} />;
132
+ * }
133
+ * ```
134
+ *
135
+ * The returned function runs the same guarded retry on demand, for content that
136
+ * becomes focusable at a moment that is neither a mount nor an activation — a
137
+ * session finishing its connect, an editor finishing its own mount. It is
138
+ * referentially stable, so it is safe in a dependency array:
139
+ *
140
+ * ```tsx
141
+ * const focusComposer = usePanelEntryFocus(api, { focus, isFocused });
142
+ *
143
+ * useEffect(() => {
144
+ * if (ready) focusComposer();
145
+ * }, [ready, focusComposer]);
146
+ * ```
147
+ *
148
+ * @param api - The surrounding panel's api ({@link DockPanelProps.api}).
149
+ * @param target - How to focus, test, and release the panel's content.
150
+ * @returns A stable callback that runs the guarded focus retry on demand.
151
+ *
152
+ * @category Consumer Services
153
+ * @public
154
+ */
155
+ export function usePanelEntryFocus(api, target) {
156
+ // Read the callbacks through a ref rather than closing over them: the
157
+ // subscription effect depends on `api` alone (re-subscribing every render
158
+ // would be worse), so a captured `target` would freeze at its first render
159
+ // and an author's inline `() => { if (enabled) … }` would go stale.
160
+ const latest = useRef(target);
161
+ useEffect(() => {
162
+ latest.current = target;
163
+ });
164
+ const focusNow = useCallback(() => {
165
+ if (!api.isActive)
166
+ return;
167
+ retryFocus(() => latest.current.focus(), () => latest.current.isFocused(), () => api.isActive);
168
+ }, [api]);
169
+ useEffect(() => {
170
+ const subActive = api.onDidActiveChange(() => {
171
+ if (api.isActive)
172
+ focusNow();
173
+ else
174
+ latest.current.blur?.();
175
+ });
176
+ // `focusNow` guards on `isActive` itself: a Focus Request says only that
177
+ // the user asked, never that this panel became active.
178
+ const subRequest = api.onDidRequestFocus(focusNow);
179
+ return () => {
180
+ subActive.dispose();
181
+ subRequest.dispose();
182
+ };
183
+ }, [api, focusNow]);
184
+ return focusNow;
185
+ }
186
+ //# sourceMappingURL=use-panel-entry-focus.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-panel-entry-focus.js","sourceRoot":"","sources":["../src/use-panel-entry-focus.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@silo-code/sdk",
3
- "version": "0.51.0",
3
+ "version": "0.52.0",
4
4
  "description": "The public, types-first SDK for building Silo extensions — the only surface third-party extensions import.",
5
5
  "license": "MIT",
6
6
  "author": "Dave Weaver",
@@ -36,10 +36,10 @@
36
36
  "react": "^19.1.0",
37
37
  "react-dom": "^19.1.0"
38
38
  },
39
- "dependencies": {},
40
39
  "devDependencies": {
41
40
  "@types/react": "^19.1.8",
42
41
  "@types/react-dom": "^19.1.0",
42
+ "jsdom": "^29.1.1",
43
43
  "typescript": "~5.8.3",
44
44
  "vitest": "^4.1.7"
45
45
  },
package/src/index.ts CHANGED
@@ -6,9 +6,9 @@
6
6
  *
7
7
  * **What's here:** the types-first extension contract (see `types.ts`) plus a
8
8
  * small set of blessed runtime helpers (`Tooltip`, the modal design-system
9
- * kit, `useFocusGroup`, `useServiceState`, `DND_MIME`, `PathDeniedError`,
10
- * `NetworkError`). The SDK peer-depends on React 19; changes to the runtime
11
- * helpers can be breaking even when the types are unchanged.
9
+ * kit, `useFocusGroup`, `usePanelEntryFocus`, `useServiceState`, `DND_MIME`,
10
+ * `PathDeniedError`, `NetworkError`). The SDK peer-depends on React 19; changes
11
+ * to the runtime helpers can be breaking even when the types are unchanged.
12
12
  *
13
13
  * This is also the entry point the API-reference generator (TypeDoc) reads, so
14
14
  * the published reference is exactly this surface — no more, no less.
@@ -356,10 +356,19 @@ export type {
356
356
  FocusGroupNavQuery,
357
357
  } from "./use-focus-group";
358
358
 
359
- // Host/InlineEdit coordination for InlineEdit's two-stage Escape (RFC 0016).
359
+ // Entry focus for a dock panel (RFC 0049): both entry signals + the
360
+ // `isActive`-guarded frame retry that wins dockview's focus shuffle, in one
361
+ // call. The one sanctioned way for panel content to take focus on entry.
362
+ export { usePanelEntryFocus } from "./use-panel-entry-focus";
363
+ export type { PanelEntryFocusTarget } from "./use-panel-entry-focus";
364
+
365
+ // Host/InlineEdit coordination for InlineEdit's two-stage Escape (RFC 0016),
366
+ // and the raw focus retry behind `usePanelEntryFocus` for the non-React
367
+ // callers that can't use the hook (RFC 0049).
360
368
  // @internal — host-only plumbing, not part of the documented reference;
361
369
  // extension authors never call these directly.
362
370
  export {
363
371
  setActiveInlineEditCancel,
364
372
  yieldEscapeToInlineEdit,
365
373
  } from "./inline-edit-controller";
374
+ export { retryFocus } from "./use-panel-entry-focus";
package/src/types.ts CHANGED
@@ -90,6 +90,37 @@ export interface DockPanelApi {
90
90
  onDidActiveChange(
91
91
  listener: (event: { readonly isActive: boolean }) => void,
92
92
  ): Disposable;
93
+ /**
94
+ * Subscribe to the user asking, by gesture, for keyboard focus in this
95
+ * panel — fired on every click of its tab, including one that leaves
96
+ * {@link DockPanelApi.isActive | isActive} unchanged because the tab was
97
+ * already active.
98
+ *
99
+ * That already-active case is why the event exists: it has no other signal.
100
+ * {@link DockPanelApi.onDidActiveChange | onDidActiveChange} only fires on a
101
+ * real transition, so clicking back into an already-active tab from
102
+ * elsewhere (a side panel, the status bar) is otherwise silent even though
103
+ * the user's intent — "put keyboard focus here" — is identical to a genuine
104
+ * activation. A panel that drives its own entry focus from
105
+ * `onDidActiveChange` should drive it from this event too, guarded on
106
+ * `isActive`, so both paths land focus the same way.
107
+ *
108
+ * The name is the intent, but today exactly one gesture carries it:
109
+ *
110
+ * - **Fires** on a primary click of this panel's tab, whether or not the
111
+ * panel was already the active one.
112
+ * - **Does not fire** for activation from anywhere else —
113
+ * {@link DockPanelApi.setActive | setActive}, a keybinding, a command or
114
+ * command-palette jump, or the host restoring a saved layout. Those change
115
+ * which panel is active, so they surface as `onDidActiveChange` instead;
116
+ * none of them reaches this event.
117
+ * - **Does not fire** for a click inside the panel's own content (focus
118
+ * there is yours to manage), the tab's close button, or a middle-click
119
+ * close.
120
+ *
121
+ * Returns a {@link Disposable} that cancels the subscription.
122
+ */
123
+ onDidRequestFocus(listener: () => void): Disposable;
93
124
  /**
94
125
  * `true` while this panel is visible — its tab is the selected one in its
95
126
  * group. Distinct from {@link DockPanelApi.isActive | isActive}: with split
@@ -0,0 +1,244 @@
1
+ /**
2
+ * @vitest-environment jsdom
3
+ */
4
+ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
5
+ import { retryFocus } from "./use-panel-entry-focus";
6
+
7
+ // The retry is the whole substance of `usePanelEntryFocus` — the hook around it
8
+ // is two subscriptions and a guard. Per the repo testing guide we drive the
9
+ // logic directly rather than rendering React: `requestAnimationFrame` is
10
+ // replaced with a hand-pumped queue so every frame is deterministic. This file
11
+ // opts into jsdom (the SDK's suite is node by default) because the retry reads
12
+ // the live `document.activeElement` to decide whether focus fell to nothing or
13
+ // moved somewhere it must not be yanked back from.
14
+ describe("retryFocus", () => {
15
+ let queue: FrameRequestCallback[] = [];
16
+ let origRaf: typeof globalThis.requestAnimationFrame;
17
+
18
+ beforeEach(() => {
19
+ queue = [];
20
+ origRaf = globalThis.requestAnimationFrame;
21
+ globalThis.requestAnimationFrame = ((cb: FrameRequestCallback) =>
22
+ queue.push(cb)) as typeof globalThis.requestAnimationFrame;
23
+ document.body.innerHTML = "";
24
+ });
25
+ afterEach(() => {
26
+ globalThis.requestAnimationFrame = origRaf;
27
+ });
28
+
29
+ /** Run exactly one scheduled frame (ticks queued during it run on the next flush). */
30
+ function flushFrame() {
31
+ const due = queue;
32
+ queue = [];
33
+ for (const cb of due) cb(0);
34
+ }
35
+
36
+ it("stops re-grabbing focus once it is no longer wanted (the region-cycle race)", () => {
37
+ const focus = vi.fn();
38
+ let wanted = true;
39
+ // Never reports focused, so without the guard it would grab every frame.
40
+ retryFocus(
41
+ focus,
42
+ () => false,
43
+ () => wanted,
44
+ );
45
+
46
+ flushFrame(); // wanted → grabs once
47
+ expect(focus).toHaveBeenCalledTimes(1);
48
+
49
+ wanted = false; // a newer focus intent superseded us
50
+ flushFrame(); // must bail BEFORE grabbing
51
+ flushFrame();
52
+ expect(focus).toHaveBeenCalledTimes(1);
53
+ });
54
+
55
+ it("re-grabs each frame until focus lands, then stops grabbing", () => {
56
+ const focus = vi.fn();
57
+ let focused = false;
58
+ retryFocus(
59
+ focus,
60
+ () => focused,
61
+ () => true,
62
+ );
63
+
64
+ flushFrame(); // not focused → grab
65
+ flushFrame(); // still not focused → grab
66
+ expect(focus).toHaveBeenCalledTimes(2);
67
+
68
+ focused = true;
69
+ flushFrame(); // landed → no further grab
70
+ expect(focus).toHaveBeenCalledTimes(2);
71
+ });
72
+
73
+ // Regression guard for symptom 1 (ADR 0034): a panel that merely re-mounts
74
+ // in the background — which happens to every panel of a workspace whose dock
75
+ // becomes visible again — must not grab focus from the tab the user actually
76
+ // left active. `stillWanted` is required precisely so a mount-time caller
77
+ // can't silently omit it and grab unconditionally.
78
+ it("never grabs on mount when the panel is not the active tab", () => {
79
+ const focus = vi.fn();
80
+ let isActive = false; // this panel re-mounted in the background
81
+ retryFocus(
82
+ focus,
83
+ () => false, // never reports focused → would grab every frame if unguarded
84
+ () => isActive,
85
+ );
86
+
87
+ flushFrame();
88
+ flushFrame();
89
+ expect(focus).not.toHaveBeenCalled();
90
+
91
+ // …and it stays bailed even if the panel becomes active later: the loop
92
+ // ended, so activation focus is the active tab's own concern, not a
93
+ // stale mount-time retry's.
94
+ isActive = true;
95
+ flushFrame();
96
+ expect(focus).not.toHaveBeenCalled();
97
+ });
98
+
99
+ it("never grabs when superseded before the first frame", () => {
100
+ const focus = vi.fn();
101
+ retryFocus(
102
+ focus,
103
+ () => false,
104
+ () => false,
105
+ );
106
+ flushFrame();
107
+ expect(focus).not.toHaveBeenCalled();
108
+ });
109
+
110
+ it("gives up after the frame cap so it never loops forever", () => {
111
+ const focus = vi.fn();
112
+ retryFocus(
113
+ focus,
114
+ () => false, // focus can never land (panel hidden, content disabled, …)
115
+ () => true,
116
+ 3,
117
+ );
118
+
119
+ for (let i = 0; i < 10; i++) flushFrame();
120
+ expect(focus).toHaveBeenCalledTimes(3);
121
+ expect(queue).toHaveLength(0);
122
+ });
123
+
124
+ it("re-grabs after landing only when focus fell to nothing", () => {
125
+ const focus = vi.fn();
126
+ let focused = true; // landed on the first frame
127
+ retryFocus(
128
+ focus,
129
+ () => focused,
130
+ () => true,
131
+ );
132
+
133
+ flushFrame(); // landed → no grab
134
+ expect(focus).not.toHaveBeenCalled();
135
+
136
+ // dockview's show/hide shuffle bounced focus off the content onto nothing.
137
+ focused = false;
138
+ flushFrame();
139
+ expect(focus).toHaveBeenCalledTimes(1);
140
+ });
141
+
142
+ it("does not yank focus back from another real element after it landed", () => {
143
+ const other = document.createElement("input");
144
+ document.body.append(other);
145
+ other.focus();
146
+
147
+ const focus = vi.fn();
148
+ let focused = true;
149
+ retryFocus(
150
+ focus,
151
+ () => focused,
152
+ () => true,
153
+ );
154
+
155
+ flushFrame(); // landed
156
+ focused = false; // the user moved on to `other` — not "lost to nothing"
157
+ flushFrame();
158
+ flushFrame();
159
+ expect(focus).not.toHaveBeenCalled();
160
+ });
161
+
162
+ describe("open menus", () => {
163
+ /** Focus a menu-like element and run one frame of a never-landing retry. */
164
+ function grabsWhileFocusedIn(menu: HTMLElement): boolean {
165
+ document.body.append(menu);
166
+ menu.tabIndex = -1;
167
+ menu.focus();
168
+ const focus = vi.fn();
169
+ retryFocus(
170
+ focus,
171
+ () => false,
172
+ () => true,
173
+ );
174
+ flushFrame();
175
+ return focus.mock.calls.length > 0;
176
+ }
177
+
178
+ // Right-clicking an *inactive* panel activates it, which starts the retry;
179
+ // without this guard the per-frame `focus()` steals focus from the menu
180
+ // that same click just opened and the menu flashes shut.
181
+ it("stands down for a Silo menu (ctx.ui.showMenu)", () => {
182
+ const menu = document.createElement("div");
183
+ menu.setAttribute("data-silo-menu", "tree-1");
184
+ menu.setAttribute("role", "menu");
185
+ expect(grabsWhileFocusedIn(menu)).toBe(false);
186
+ });
187
+
188
+ it("stands down for a Monaco context menu", () => {
189
+ const menu = document.createElement("div");
190
+ menu.className = "context-view";
191
+ expect(grabsWhileFocusedIn(menu)).toBe(false);
192
+ });
193
+
194
+ // Monaco renders its context menu into a shadow root, so from the light DOM
195
+ // `document.activeElement` is only the host element — the menu nodes live
196
+ // one level down, which is why a plain `closest` isn't enough.
197
+ it("stands down for a menu inside a shadow root", () => {
198
+ const host = document.createElement("div");
199
+ document.body.append(host);
200
+ const shadow = host.attachShadow({ mode: "open" });
201
+ const menu = document.createElement("div");
202
+ menu.className = "monaco-menu";
203
+ shadow.append(menu);
204
+ host.tabIndex = -1;
205
+ host.focus();
206
+
207
+ const focus = vi.fn();
208
+ retryFocus(
209
+ focus,
210
+ () => false,
211
+ () => true,
212
+ );
213
+ flushFrame();
214
+ expect(focus).not.toHaveBeenCalled();
215
+ });
216
+
217
+ it("ends the loop rather than resuming once the menu closes", () => {
218
+ const menu = document.createElement("div");
219
+ menu.setAttribute("data-silo-menu", "tree-1");
220
+ menu.tabIndex = -1;
221
+ document.body.append(menu);
222
+ menu.focus();
223
+
224
+ const focus = vi.fn();
225
+ retryFocus(
226
+ focus,
227
+ () => false,
228
+ () => true,
229
+ );
230
+ flushFrame(); // bails
231
+ expect(queue).toHaveLength(0);
232
+
233
+ // Nothing rescheduled: the menu's owner restores content focus itself.
234
+ menu.remove();
235
+ flushFrame();
236
+ expect(focus).not.toHaveBeenCalled();
237
+ });
238
+
239
+ it("still grabs when focus is merely on the body, not a menu", () => {
240
+ const plain = document.createElement("div");
241
+ expect(grabsWhileFocusedIn(plain)).toBe(true);
242
+ });
243
+ });
244
+ });
@@ -0,0 +1,237 @@
1
+ import { useCallback, useEffect, useRef } from "react";
2
+ import type { DockPanelApi } from "./types";
3
+
4
+ // Entry focus for a dock panel — landing the caret in the panel's content when
5
+ // the user enters it.
6
+ //
7
+ // A freshly-mounted or newly-activated dock panel does NOT reliably inherit DOM
8
+ // focus: dockview runs its own focus shuffle when panels mount/activate, and
9
+ // rich content (Monaco, xterm) only accepts focus once its internal textarea
10
+ // has been laid out with non-zero dimensions. A single `focus()` call loses
11
+ // these races, which is why a panel would otherwise need a second click before
12
+ // you can type. We retry across animation frames until the target actually
13
+ // reports focus, the panel is no longer the one we wanted to focus, or we hit a
14
+ // frame cap (~330ms) so we never loop forever when focus legitimately can't be
15
+ // grabbed (panel hidden, content disabled, etc.).
16
+
17
+ const DEFAULT_CAP = 20;
18
+
19
+ // Every menu implementation whose open state must suppress the retry: Silo's
20
+ // own menus (`ctx.ui.showMenu`, which renders `[data-silo-menu]` with
21
+ // `role="menu"`), a third-party menu that follows the same ARIA role, and
22
+ // Monaco's context menu (`.context-view` / `.monaco-menu`).
23
+ const MENU_SELECTOR =
24
+ '[data-silo-menu], [role="menu"], .context-view, .monaco-menu';
25
+
26
+ /**
27
+ * Whether focus currently sits inside an open floating menu. Monaco renders its
28
+ * context menu into a shadow root, where `document.activeElement` resolves only
29
+ * to the open `shadow-root-host` and the menu nodes hang off its `shadowRoot` —
30
+ * hence the shadow peek, not just a light-DOM `closest`.
31
+ */
32
+ function focusInMenu(active: Element | null): boolean {
33
+ if (!active) return false;
34
+ if (active.closest(MENU_SELECTOR)) return true;
35
+ return active.shadowRoot?.querySelector(MENU_SELECTOR) != null;
36
+ }
37
+
38
+ /**
39
+ * Repeatedly call `focus()` on successive animation frames until `isFocused()`
40
+ * returns true, `stillWanted()` returns false, or `cap` frames have elapsed.
41
+ *
42
+ * `stillWanted` is **required**, and must express "this panel is still the one
43
+ * that should hold focus" — normally `() => api.isActive`, or the center
44
+ * dock's focus-intent token (`focusGen`). It is deliberately not optional: a
45
+ * retry loop without it keeps grabbing focus for its entire frame budget no
46
+ * matter what else happened meanwhile. That matters most on *mount*, because
47
+ * re-entering a workspace re-mounts its panels — so an unguarded mount-time
48
+ * grab in a background tab yanks focus away from the tab the user actually
49
+ * left active. And because DOM focus landing inside a dockview panel makes
50
+ * dockview mark that panel's group active
51
+ * (`contentContainer.onDidFocus → doSetGroupActive`), stealing focus silently
52
+ * changes the visible active tab too. That was symptom 1 in ADR 0034.
53
+ *
54
+ * Panel content should reach for {@link usePanelEntryFocus} instead, which
55
+ * supplies the guard and both entry subscriptions for you. This raw form is
56
+ * host/`core.*` plumbing for the non-React callers that can't.
57
+ *
58
+ * @internal
59
+ */
60
+ export function retryFocus(
61
+ focus: () => void,
62
+ isFocused: () => boolean,
63
+ stillWanted: () => boolean,
64
+ cap = DEFAULT_CAP,
65
+ ): void {
66
+ let attempts = 0;
67
+ let landed = false;
68
+ const tick = () => {
69
+ // Bail before touching focus if we're no longer wanted — a newer focus
70
+ // intent superseded us (e.g. the user kept pressing the region-cycle chord).
71
+ // Checked here, not just after the grab below, so a stale retry can't yank
72
+ // focus back from the area the user actually moved to.
73
+ if (!stillWanted()) return;
74
+ attempts += 1;
75
+ if (isFocused()) {
76
+ landed = true;
77
+ } else {
78
+ // Before focus first lands, grab aggressively each frame — Monaco/xterm
79
+ // only accept focus once their textarea is laid out, so early calls lose.
80
+ // After it has landed, only re-grab if focus fell to NOTHING (<body>/null):
81
+ // dockview's show/hide shuffle can bounce focus off the just-focused
82
+ // content a frame or two later (the "keystrokes dropped after a switch"
83
+ // symptom). We watch the full frame budget to catch that — but never yank
84
+ // focus away from another real element the user may have moved to.
85
+ const active = document.activeElement;
86
+ // Focus legitimately moved into an open context menu — don't yank it
87
+ // back, or the menu's focus-out dismiss fires and it flashes shut.
88
+ // Right-clicking an *inactive* panel activates it, which starts this
89
+ // retry; without the guard the per-frame `focus()` steals focus from the
90
+ // just-opened menu (the focused case never starts the retry, which is why
91
+ // the bug only shows when the panel was unfocused). End the loop: the
92
+ // menu's owner restores content focus itself once the menu closes.
93
+ if (focusInMenu(active)) return;
94
+ const lostToNothing = active === null || active === document.body;
95
+ if (!landed || lostToNothing) focus();
96
+ }
97
+ if (attempts >= cap || !stillWanted()) return;
98
+ requestAnimationFrame(tick);
99
+ };
100
+ requestAnimationFrame(tick);
101
+ }
102
+
103
+ /**
104
+ * The content {@link usePanelEntryFocus} drives — how to focus it, how to tell
105
+ * whether it already has focus, and optionally how to release it.
106
+ *
107
+ * All three are called through a latest-ref, so inline closures over props or
108
+ * state are always current; you never need to memoize them.
109
+ *
110
+ * @category Core Types
111
+ * @public
112
+ */
113
+ export interface PanelEntryFocusTarget {
114
+ /**
115
+ * Imperatively focus the panel's content — e.g. `() => inputRef.current?.focus()`
116
+ * or `() => editor.focus()`. Safe to make a no-op while the content isn't
117
+ * ready to take focus; the retry simply expires.
118
+ */
119
+ focus: () => void;
120
+ /**
121
+ * Whether the content holds DOM keyboard focus **right now**, so the retry
122
+ * can stop as soon as it lands instead of burning the whole frame budget.
123
+ *
124
+ * Read the live `document.activeElement` — e.g.
125
+ * `() => document.activeElement === inputRef.current`. Don't trust a
126
+ * library's own tracker flag (Monaco's `hasTextFocus()`, say): those go
127
+ * stale-true when a blur is dropped during dockview's show/hide shuffle,
128
+ * which stops the retry believing focus landed when it didn't.
129
+ */
130
+ isFocused: () => boolean;
131
+ /**
132
+ * Release the content's focus when the panel's tab is deactivated. Only
133
+ * needed for content that tracks its own focus state internally — a Monaco
134
+ * editor or an xterm terminal is kept alive (hidden) while its tab is
135
+ * inactive, and if its tracker stays stuck believing it has focus it will
136
+ * steal keystrokes meant for the tab you switched to. A plain input needs
137
+ * nothing here.
138
+ */
139
+ blur?: () => void;
140
+ }
141
+
142
+ /**
143
+ * Land keyboard focus in a dock panel's content whenever the user enters the
144
+ * panel, winning dockview's focus shuffle — and, symmetrically, release it when
145
+ * the panel's tab is deactivated.
146
+ *
147
+ * A panel that puts the cursor somewhere on entry (a chat composer, a search
148
+ * box, an editor) needs three things that are easy to get individually wrong,
149
+ * and this hook is all three in one call:
150
+ *
151
+ * 1. **Both entry signals.** {@link DockPanelApi.onDidActiveChange} covers real
152
+ * activations. {@link DockPanelApi.onDidRequestFocus} covers a click on a
153
+ * tab that was *already* active — dockview treats that as a complete no-op
154
+ * and fires no active-change event, even though it is the commonest way a
155
+ * user asks for the cursor back (they were typing in a side panel, clicked
156
+ * the status bar, then clicked your tab).
157
+ * 2. **A guard.** Focus is only ever taken while the panel is the active one.
158
+ * Mount is not "the user just created this panel" — re-entering a workspace
159
+ * re-mounts every panel in its dock — and DOM focus landing in a panel makes
160
+ * dockview activate its group, so an unguarded grab silently changes the
161
+ * visible tab (ADR 0034).
162
+ * 3. **A retry.** A single `focus()` loses dockview's shuffle, and rich content
163
+ * only accepts focus once its internal textarea is laid out. The hook
164
+ * retries across frames until focus lands, standing down if the panel stops
165
+ * being active or focus moves into an open context menu.
166
+ *
167
+ * ```tsx
168
+ * function AcmeChatPanel({ api }: DockPanelProps) {
169
+ * const input = useRef<HTMLTextAreaElement | null>(null);
170
+ *
171
+ * usePanelEntryFocus(api, {
172
+ * focus: () => input.current?.focus(),
173
+ * isFocused: () => document.activeElement === input.current,
174
+ * });
175
+ *
176
+ * return <textarea ref={input} />;
177
+ * }
178
+ * ```
179
+ *
180
+ * The returned function runs the same guarded retry on demand, for content that
181
+ * becomes focusable at a moment that is neither a mount nor an activation — a
182
+ * session finishing its connect, an editor finishing its own mount. It is
183
+ * referentially stable, so it is safe in a dependency array:
184
+ *
185
+ * ```tsx
186
+ * const focusComposer = usePanelEntryFocus(api, { focus, isFocused });
187
+ *
188
+ * useEffect(() => {
189
+ * if (ready) focusComposer();
190
+ * }, [ready, focusComposer]);
191
+ * ```
192
+ *
193
+ * @param api - The surrounding panel's api ({@link DockPanelProps.api}).
194
+ * @param target - How to focus, test, and release the panel's content.
195
+ * @returns A stable callback that runs the guarded focus retry on demand.
196
+ *
197
+ * @category Consumer Services
198
+ * @public
199
+ */
200
+ export function usePanelEntryFocus(
201
+ api: DockPanelApi,
202
+ target: PanelEntryFocusTarget,
203
+ ): () => void {
204
+ // Read the callbacks through a ref rather than closing over them: the
205
+ // subscription effect depends on `api` alone (re-subscribing every render
206
+ // would be worse), so a captured `target` would freeze at its first render
207
+ // and an author's inline `() => { if (enabled) … }` would go stale.
208
+ const latest = useRef(target);
209
+ useEffect(() => {
210
+ latest.current = target;
211
+ });
212
+
213
+ const focusNow = useCallback(() => {
214
+ if (!api.isActive) return;
215
+ retryFocus(
216
+ () => latest.current.focus(),
217
+ () => latest.current.isFocused(),
218
+ () => api.isActive,
219
+ );
220
+ }, [api]);
221
+
222
+ useEffect(() => {
223
+ const subActive = api.onDidActiveChange(() => {
224
+ if (api.isActive) focusNow();
225
+ else latest.current.blur?.();
226
+ });
227
+ // `focusNow` guards on `isActive` itself: a Focus Request says only that
228
+ // the user asked, never that this panel became active.
229
+ const subRequest = api.onDidRequestFocus(focusNow);
230
+ return () => {
231
+ subActive.dispose();
232
+ subRequest.dispose();
233
+ };
234
+ }, [api, focusNow]);
235
+
236
+ return focusNow;
237
+ }