/** * settingsDom.ts — 官方设置弹窗的 DOM 契约(official/ 层)。 * * official/ 只做一件事:**找到并描述**宿主节点,不替消费方做决策 —— 加类、 * 改样式、拦事件都留在 patches/ 与 motion/。这里每个函数都是纯探测:命中就 * 返回节点或几何值,未命中安静返回 null(宿主是 CSS-module hash 的上游包, * 结构变了要降级成"没找到",不能抛错)。 * * 宿主(@deepseek-ai/dsh-client-ui-settings-general 的 SettingsRoot)结构: * * div.overlay[role="presentation"] * ├── div.mask[aria-hidden="true"] ← 弹窗的前一个兄弟 * └── div.panel[role="dialog"][aria-modal="true"] * ├── nav > div.navList ← 左侧 tab 列 * └── div.content > div.header > (div.actions, button.close) * * 两个消费方对"这是不是设置弹窗"的口径本来就不一样,本模块把两种口径收在一处 * (而不是让它们各自维护一份假设): * - `findDialogWithNavRail()` 宽口径:modal dialog + 直接子级 nav。窗口化补丁用它 —— * 补丁只改外框尺寸/位置,认错弹窗的代价仅是多给一个弹窗加了把手; * - `isSettingsDialog()` / `findSettingsDialog()` 严口径:再要求"挂在 role=presentation * 层里、且紧邻自己的遮罩"。动效引擎用它 —— 它要拦关闭点击,把别的插件的可 * 导航弹窗当成设置面板会吞掉不属于它的交互。 */ /** * 设置弹窗选择器:带 `aria-modal` 的 dialog。 * * 历史上两份声明不一致(`div[role="dialog"]…` 与 `[role="dialog"]…`)。实测宿主现存 * 四个 modal 实现(ui-settings-general/SettingsRoot、ui-primitives/Modal、 * ui-primitives/ImageLightbox、ui-settings-account/PlatformOverlay)渲染的都是 * `
`,两种写法在真实 DOM 上等价;取带 `div` * 前缀这份更精确(不会匹配将来可能出现的非 div 自定义元素),故统一到它。 */ export declare const SETTINGS_DIALOG_SELECTOR = "div[role=\"dialog\"][aria-modal=\"true\"]"; /** * 设置弹窗挂载层:壳组件用 `role="presentation"` 的 overlay 承载遮罩与弹窗。 * It is the one structural fact that tells the settings modal apart from any other * modal that happens to render a nav rail. */ export declare const OVERLAY_ROLE = "presentation"; /** * The panel's own mask: the `aria-hidden` sibling immediately before it. A * sibling that CONTAINS the panel is a container, not a mask - returning it would * make `mask.contains(target)` true for every click in the page and swallow them * all. * @param dialog - the settings dialog. */ export declare function maskOf(dialog: Element): HTMLElement | null; /** * True for the host settings dialog: a modal dialog with a nav rail, mounted in * the shell's `role="presentation"` layer next to its own mask. Requiring that * layer and the mask sibling matters - "modal + nav" alone also accepts other * plugins' navigable modals, and taking one of those for the panel made this * engine intercept clicks that are none of its business. * @param node - a candidate dialog element. */ export declare function isSettingsDialog(node: Element): boolean; /** * 严口径查找:第一个真正的设置弹窗(见 `isSettingsDialog()`),没有则 null。 * * 与 `findDialogWithNavRail()` 的差别:这里额外要求 overlay 层与遮罩兄弟, * 且 nav 只要求"存在"(任意深度)—— 动效引擎的关闭拦截宁可漏认,也不认错。 */ export declare function findSettingsDialog(): HTMLElement | null; /** * 宽口径查找:第一个"modal dialog 且直接子级含