skills-experimental/focus-manager/SKILL.md
# Focus Manager Skill Focus Manager - FocusManager class + MAX_FOCUS_STACK + deduplicate stack + handleNodeRemoved + activeElement tracking + FocusEvent dispatch。 ## 功能概述 从Claude Code的ink/focus.ts提取的焦点管理模式,用于OpenClaw的UI焦点管理。 ## 核心机制 ### FocusManager Class ```typescript export class FocusManager { activeElement: DOMElement | null = null private enabled = true private focusStack: DOMElement[] = [] constructor(dispatchFocusEvent: (target, event) => boolean) { this.dispatchFocus
npx skillsauth add bianhaifeng789-hue/openclaw-config skills-experimental/focus-managerInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Focus Manager - FocusManager class + MAX_FOCUS_STACK + deduplicate stack + handleNodeRemoved + activeElement tracking + FocusEvent dispatch。
从Claude Code的ink/focus.ts提取的焦点管理模式,用于OpenClaw的UI焦点管理。
export class FocusManager {
activeElement: DOMElement | null = null
private enabled = true
private focusStack: DOMElement[] = []
constructor(dispatchFocusEvent: (target, event) => boolean) {
this.dispatchFocusEvent = dispatchFocusEvent
}
}
// Class for DOM-like focus management
// activeElement: current focus
// focusStack: history stack
// enabled: toggle
const MAX_FOCUS_STACK = 32
if (this.focusStack.length > MAX_FOCUS_STACK) {
this.focusStack.shift() // Remove oldest
}
// Bounded stack size
// Prevent unbounded growth
// 32 elements max
// Deduplicate before pushing to prevent unbounded growth from Tab cycling
const idx = this.focusStack.indexOf(previous)
if (idx !== -1) this.focusStack.splice(idx, 1)
this.focusStack.push(previous)
// Remove if already exists
// Prevent duplicates from Tab cycling
// Keep stack bounded
/**
* Called by reconciler when node is removed from tree.
* Handles both the exact node AND any focused descendant within
* the removed subtree. Dispatches blur and restores from stack.
*/
handleNodeRemoved(node: DOMElement, root: DOMElement): void {
// Remove node and descendants from stack
this.focusStack = this.focusStack.filter(
n => n !== node && isInTree(n, root),
)
// Check if activeElement is removed node OR descendant
if (!this.activeElement) return
if (this.activeElement !== node && isInTree(this.activeElement, root)) {
return
}
const removed = this.activeElement
this.activeElement = null
this.dispatchFocusEvent(removed, new FocusEvent('blur', null))
// Restore focus to most recent still-mounted element
while (this.focusStack.length > 0) {
const candidate = this.focusStack.pop()!
if (isInTree(candidate, root)) {
this.activeElement = candidate
this.dispatchFocusEvent(candidate, new FocusEvent('focus', removed))
return
}
}
}
// Reconciler call on node removal
// Handle node and descendants
// Restore from stack
focus(node: DOMElement): void {
if (node === this.activeElement) return
if (!this.enabled) return
const previous = this.activeElement
if (previous) {
// Deduplicate + push to stack
this.dispatchFocusEvent(previous, new FocusEvent('blur', node))
}
this.activeElement = node
this.dispatchFocusEvent(node, new FocusEvent('focus', previous))
}
blur(): void {
if (!this.activeElement) return
const previous = this.activeElement
this.activeElement = null
this.dispatchFocusEvent(previous, new FocusEvent('blur', null))
}
// Focus: previous blur + node focus
// Blur: activeElement to null
// FocusEvent dispatch
import { FocusEvent } from './events/focus-event.js'
new FocusEvent('blur', relatedTarget)
new FocusEvent('focus', relatedTarget)
// FocusEvent type + relatedTarget
// Like DOM FocusEvent
// Check if node is still in tree (mounted)
if (isInTree(candidate, root)) { ... }
// Verify node still mounted
// Before restoring focus
// Prevent focus on removed node
{
"activeElement": "input-box",
"focusStackSize": 5,
"enabled": true
}
MAX_FOCUS_STACK = 32 → shift() on overflow → bounded growth
// 32上限
// overflow时shift最旧
indexOf(previous) → splice if exists → push → no duplicates
// Tab cycling可能重复
// 先检查再push
handleNodeRemoved → filter stack + check activeElement + restore from stack
// node移除时处理
// 检查descendant
// stack恢复focus
while (stack.length > 0) → pop + isInTree check → restore
// 循环pop直到找到mounted element
// isInTree验证
ink/focus.tsbusiness
IAA 日报飞书输出能力。 支持把固定 CSV 模板一键转换成: - 中文运营结论 - 飞书卡片 JSON - 飞书发送载荷 Use when: - 需要把 IAA 日报直接发到飞书 - 需要从 CSV 一键生成运营日报
data-ai
IAA日报分析模型 功能: - 渠道日报自动分析 - 小时级+日级ROI联动判断 - 按地区输出加量/降量/停投建议 - 按产品类型输出阈值 - 自动识别利润区/观察区/止损区 Use when: - 分析每天投放数据 - 生成运营日报结论 - 判断是否加量/降量/停投 - 对比美加澳/日韩表现 Keywords: - 日报模型, 投放日报, 加量, 降量, 停投, ROI日报, 分地区分析
data-ai
IAA固定日报分析模板 功能: - 固定字段模板(可直接贴每天数据) - 自动输出总盘结论 - 自动输出美加澳/日韩结论 - 自动给出加量/降量/停投建议 - 适配文件修复/清理两类产品 Use when: - 需要固定日报格式 - 每天复盘渠道表现 - 给运营团队出统一结论 Keywords: - 固定模板, 日报模板, ROI模板, IAA日报, 运营模板
development
# HyperlinkPool Pattern Skill HyperlinkPool Pattern - HyperlinkPool class + strings array + stringMap + Index 0 no hyperlink + intern(hyperlink) + get(id) + undefined handling + 5-minute reset + OSC8 hyperlink interning。 ## 功能概述 从Claude Code的ink/screen.ts提取的HyperlinkPool模式,用于OpenClaw的OSC8超链接池管理。 ## 核心机制 ### HyperlinkPool Class ```typescript export class HyperlinkPool { private strings: string[] = [''] // Index 0 = no hyperlink private stringMap = new Map<string, number>() // strings