dsh-task-ledger 0.0.95 → 0.0.97

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/dist/client.js +3618 -116
  2. package/dist/client.js.map +1 -1
  3. package/dist/host/repositories/ledger.repository.d.ts +8 -2
  4. package/dist/host/repositories/ledger.repository.js +4 -1
  5. package/dist/host/repositories/records.d.ts +10 -2
  6. package/dist/host/repositories/records.js +11 -2
  7. package/dist/host/routes.js +1 -0
  8. package/dist/host/services/dates.d.ts +7 -2
  9. package/dist/host/services/dates.js +29 -6
  10. package/dist/host/services/history.service.js +1 -1
  11. package/dist/host/services/trend.service.d.ts +4 -1
  12. package/dist/host/services/trend.service.js +9 -1
  13. package/package.json +4 -1
  14. package/skill/README.md +2 -2
  15. package/skill/SKILL.md +34 -13
  16. package/skill/assets/worklog.md +1 -0
  17. package/skill/package.json +1 -1
  18. package/skill/references/state-model.md +6 -1
  19. package/skill/references/troubleshooting.md +5 -5
  20. package/skill/scripts/ledgerkit/actions/claim.py +7 -2
  21. package/skill/scripts/ledgerkit/actions/close_task.py +8 -0
  22. package/skill/scripts/ledgerkit/actions/handoff.py +5 -2
  23. package/skill/scripts/ledgerkit/actions/list_tasks.py +4 -1
  24. package/skill/scripts/ledgerkit/actions/log_progress.py +6 -2
  25. package/skill/scripts/ledgerkit/actions/new_task.py +7 -1
  26. package/skill/scripts/ledgerkit/actions/query_history.py +3 -1
  27. package/skill/scripts/ledgerkit/actions/release.py +6 -2
  28. package/skill/scripts/ledgerkit/actions/result.py +2 -0
  29. package/skill/scripts/ledgerkit/actions/show_task.py +31 -4
  30. package/skill/scripts/ledgerkit/actions/validate.py +6 -49
  31. package/skill/scripts/ledgerkit/core/history_md.py +18 -13
  32. package/skill/scripts/ledgerkit/core/time.py +2 -1
  33. package/skill/scripts/ledgerkit/core/worklog_md.py +137 -8
  34. package/skill/scripts/ledgerkit/shell/cli.py +24 -2
  35. package/skill/scripts/ledgerkit/shell/render.py +48 -4
  36. package/skill/scripts/ledgerkit/store/worklog_store.py +15 -4
@@ -1 +1 @@
1
- {"version":3,"file":"client.js","names":["h","Tooltip","useState","h","Tooltip","IconSearchOutlineRegular","IconDownloadOutlineRegular","IconChevronRightOutlineRegular","IconCheckOutlineRegular","useSyncExternalStore","useState","useMemo","h","IconRefreshOutlineRegular","IconChecklistOutlineRegular","IconFlatListOutlineRegular","IconFolderOpenRegular","IconFolderCloseRegular","h"],"sources":["../src/client/rows.ts","../src/client/api.ts","../src/client/store.ts","../src/client/format.ts","../src/client/tokens.ts","../src/client/ui.ts","../src/client/task-row.ts","../src/client/board-home.ts","../src/client/locales.ts","../src/client/index.ts"],"sourcesContent":["/**\n * 列表视图的筛选 / 分区 / 排序(**唯一**实现,纯函数、不碰网络):页面只渲染,不各写一份过滤。\n * 定稿见 docs/design/features/board-home.md §二.3:两区结构(我的待办平铺 / 按工作区分组),\n * 已结案**不在首页**(去统计 tab)。\n *\n * 单独成文件是为了能被冒烟直测(store.ts 引 api.ts,Node 剥类型解析不了无扩展名相对导入)。\n */\n\nimport type { Query } from \"./store\";\nimport type { BoardPayload, BoardTask, HistoryRecord } from \"./types\";\n\n/** 列表行:在办与已结案两套形状,行件按 kind 分支(不做「统一成一个假结构」的归一化)。 */\nexport type Row =\n\t| { kind: \"task\"; key: string; task: BoardTask; mine: boolean }\n\t| { kind: \"closed\"; key: string; record: HistoryRecord };\n\n/**\n * 界面上显示人名的**唯一**口径:显示名(`owner_name` / `creator_name`)优先,\n * 旧数据 / 名册里没名字才退回 uuid。**只用于显示与搜索** —— 归属判定一律比 uuid(见 `isMine`)。\n */\nexport function displayName(\n\tname: string | null | undefined,\n\tuuid: string | null | undefined,\n): string {\n\tconst label = (name ?? \"\").trim();\n\treturn label !== \"\" ? label : (uuid ?? \"\").trim();\n}\n\n/** 一个工作区分组(计数口径:待认领 / 进行中 / 积压 / 逾期 / 停滞 / 总,供「全部待办」段头统计)。 */\nexport interface WorkspaceGroup {\n\treadonly workspaceId: string;\n\treadonly title: string;\n\treadonly doingCount: number;\n\treadonly overdueCount: number;\n\treadonly staleCount: number;\n\treadonly backlogCount: number;\n\treadonly openCount: number;\n\treadonly total: number;\n\treadonly rows: readonly Row[];\n}\n\n/** 两区视图:第一区我的待办 + 第二区按工作区分组(第二区含全部任务,会与第一区重叠——用户 2026-10-18 要「全部待办」)。 */\nexport interface BoardView {\n\treadonly mine: readonly Row[];\n\treadonly groups: readonly WorkspaceGroup[];\n\t/** 第二区(全部待办)任务数。 */\n\treadonly total: number;\n\t/** 第二区全量计数(**不受状态过滤影响**,供 segmented 角标;异常标记相互独立;含我的)。 */\n\treadonly allCounts: {\n\t\treadonly total: number;\n\t\treadonly doing: number;\n\t\treadonly open: number;\n\t\treadonly overdue: number;\n\t\treadonly stale: number;\n\t\treadonly backlog: number;\n\t};\n}\n\n/** 关键字命中(标题 / 任务号 / 人 / 分类 / 标签;已结案另含「完成了什么」)。 */\nfunction hitKeyword(\n\tkeyword: string,\n\tparts: readonly (string | null | undefined)[],\n): boolean {\n\tconst needle = keyword.trim().toLowerCase();\n\tif (needle === \"\") return true;\n\treturn parts.some((part) => part?.toLowerCase().includes(needle) === true);\n}\n\n/** uuid 比较:两边都 trim + 小写(身份键不分大小写,与脚本 `normalize` 同口径)。 */\nexport function sameUuid(\n\ta: string | null | undefined,\n\tb: string | null | undefined,\n): boolean {\n\tconst left = (a ?? \"\").trim().toLowerCase();\n\tconst right = (b ?? \"\").trim().toLowerCase();\n\treturn left !== \"\" && left === right;\n}\n\n/** 「我的」判定:owner = 本机身份 uuid,且状态是进行中(blocked 是旧数据,照收;与 host 同口径)。 */\nexport function isMine(task: BoardTask, board: BoardPayload | null): boolean {\n\tif (board === null) return false;\n\tconst identity = board.identities[task.workspace.id] ?? null;\n\tif (identity === null || identity === \"\") return false;\n\treturn (\n\t\tsameUuid(task.owner, identity) &&\n\t\t(task.status === \"doing\" || task.status === \"blocked\")\n\t);\n}\n\n/**\n * 任务动作权限(**唯一**判定,两区共用——用户 2026-10-18:不许各判各的)。\n * 传任务 + 快照进去,返回「能做哪些动作」;界面只按返回值画按钮,不再自己判断是不是我的。\n * ⇒ 第二区(全部待办)里**我的**任务也能继续 / 结束 / 释放,跟第一区一模一样。\n */\nexport interface TaskActions {\n\t/** 查看详情(两区、所有任务都有)。 */\n\treadonly view: boolean;\n\t/** 认领:只有**没人认领**(待认领)的任务能认领。 */\n\treadonly claim: boolean;\n\treadonly resume: boolean;\n\treadonly finish: boolean;\n\treadonly release: boolean;\n}\n\nexport function resolveActions(\n\ttask: BoardTask,\n\tboard: BoardPayload | null,\n): TaskActions {\n\tconst mine = isMine(task, board);\n\treturn {\n\t\tview: true,\n\t\tclaim: !mine && task.status === \"open\",\n\t\tresume: mine,\n\t\tfinish: mine,\n\t\trelease: mine,\n\t};\n}\n\n/** 已结案行(统计 tab):只有查看,没有在办动作。 */\nexport const CLOSED_ACTIONS: TaskActions = {\n\tview: true,\n\tclaim: false,\n\tresume: false,\n\tfinish: false,\n\trelease: false,\n};\n\n/** 状态档命中(积压 / 逾期 / 停滞由 host 标记,前端不判阈值)——只作用于第二区。 */\nfunction statusHit(task: BoardTask, status: Query[\"status\"]): boolean {\n\tif (status === \"all\") return true;\n\tif (status === \"active\")\n\t\treturn task.status === \"doing\" || task.status === \"blocked\";\n\tif (status === \"open\") return task.status === \"open\";\n\tif (status === \"backlog\") return task.backlog === true;\n\tif (status === \"overdue\") return task.overdue === true;\n\treturn task.stale === true;\n}\n\n/** 组内排序:别人的进行中在前、待认领在后;各自按创建 / 开始时间倒序。 */\nfunction inGroupOrder(a: Row, b: Row): number {\n\tif (a.kind !== \"task\" || b.kind !== \"task\") return 0;\n\tconst rank = (task: BoardTask): number => (task.status === \"open\" ? 1 : 0);\n\tif (rank(a.task) !== rank(b.task)) return rank(a.task) - rank(b.task);\n\treturn String(b.task.created ?? b.task.started ?? \"\").localeCompare(\n\t\tString(a.task.created ?? a.task.started ?? \"\"),\n\t);\n}\n\n/**\n * 当前筛选下的两区视图(用户 2026-10-18 调整):\n * - 第一区「我的待办」= 我名下 doing/blocked,吃工作区下拉 + 标题搜索,按创建时间倒序;\n * - 第二区「全部待办」= **所有**在办任务按工作区分组(含我的——用户明确不要过滤掉自己),\n * 吃**状态档**(segmented)+ **标题 / 执行人搜索**(othersKeyword);一个整表(外框连着)。\n * ⇒ 我的任务会同时出现在两个区,这是预期(顶部快看 / 底部全量)。\n */\nexport function selectView(current: {\n\tboard: BoardPayload | null;\n\tquery: Query;\n}): BoardView {\n\tconst { board, query } = current;\n\tif (board === null) {\n\t\treturn {\n\t\t\tmine: [],\n\t\t\tgroups: [],\n\t\t\ttotal: 0,\n\t\t\tallCounts: {\n\t\t\t\ttotal: 0,\n\t\t\t\tdoing: 0,\n\t\t\t\topen: 0,\n\t\t\t\toverdue: 0,\n\t\t\t\tstale: 0,\n\t\t\t\tbacklog: 0,\n\t\t\t},\n\t\t};\n\t}\n\tconst allTasks = board.tasks;\n\tconst allCounts = {\n\t\ttotal: allTasks.length,\n\t\tdoing: allTasks.filter((task) => task.status === \"doing\").length,\n\t\topen: allTasks.filter((task) => task.status === \"open\").length,\n\t\toverdue: allTasks.filter((task) => task.overdue === true).length,\n\t\tstale: allTasks.filter((task) => task.stale === true).length,\n\t\tbacklog: allTasks.filter((task) => task.backlog === true).length,\n\t};\n\tconst mineRows: Row[] = board.tasks\n\t\t.filter((task) => isMine(task, board))\n\t\t.filter(\n\t\t\t(task) => query.workspace === \"\" || task.workspace.id === query.workspace,\n\t\t)\n\t\t.filter((task) =>\n\t\t\thitKeyword(query.keyword, [\n\t\t\t\ttask.title,\n\t\t\t\ttask.id,\n\t\t\t\t// 搜的是**人名**:uuid 是机器键,人不会拿它搜\n\t\t\t\tdisplayName(task.owner_name, task.owner),\n\t\t\t\tdisplayName(task.creator_name, task.creator),\n\t\t\t\ttask.category,\n\t\t\t\t...(task.tags ?? []),\n\t\t\t]),\n\t\t)\n\t\t.sort((a, b) =>\n\t\t\tString(b.created ?? b.started ?? \"\").localeCompare(\n\t\t\t\tString(a.created ?? a.started ?? \"\"),\n\t\t\t),\n\t\t)\n\t\t.map(\n\t\t\t(task): Row => ({\n\t\t\t\tkind: \"task\",\n\t\t\t\tkey: `${task.workspace.id}:${task.id}`,\n\t\t\t\ttask,\n\t\t\t\tmine: true,\n\t\t\t}),\n\t\t);\n\tconst rest =\n\t\tquery.scope === \"mine\"\n\t\t\t? []\n\t\t\t: board.tasks\n\t\t\t\t\t.filter((task) => statusHit(task, query.status))\n\t\t\t\t\t.filter((task) =>\n\t\t\t\t\t\thitKeyword(query.othersKeyword, [\n\t\t\t\t\t\t\ttask.title,\n\t\t\t\t\t\t\tdisplayName(task.owner_name, task.owner),\n\t\t\t\t\t\t]),\n\t\t\t\t\t);\n\tconst byWorkspace = new Map<string, { title: string; rows: Row[] }>();\n\tfor (const task of rest) {\n\t\tconst entry = byWorkspace.get(task.workspace.id) ?? {\n\t\t\ttitle: task.workspace.title,\n\t\t\trows: [],\n\t\t};\n\t\t// mine 必须说实话(第二区现在含全部任务,连我的也在里面):按钮权限由 resolveActions 判,\n\t\t// 但这一位同样是数据面,不许一律写 false。\n\t\tentry.rows.push({\n\t\t\tkind: \"task\",\n\t\t\tkey: `${task.workspace.id}:${task.id}`,\n\t\t\ttask,\n\t\t\tmine: isMine(task, board),\n\t\t});\n\t\tbyWorkspace.set(task.workspace.id, entry);\n\t}\n\tconst groups: WorkspaceGroup[] = [...byWorkspace.entries()]\n\t\t.map(([workspaceId, entry]) => ({\n\t\t\tworkspaceId,\n\t\t\ttitle: entry.title,\n\t\t\tdoingCount: entry.rows.filter(\n\t\t\t\t(row) => row.kind === \"task\" && row.task.status === \"doing\",\n\t\t\t).length,\n\t\t\toverdueCount: entry.rows.filter(\n\t\t\t\t(row) => row.kind === \"task\" && row.task.overdue === true,\n\t\t\t).length,\n\t\t\tstaleCount: entry.rows.filter(\n\t\t\t\t(row) => row.kind === \"task\" && row.task.stale === true,\n\t\t\t).length,\n\t\t\tbacklogCount: entry.rows.filter(\n\t\t\t\t(row) => row.kind === \"task\" && row.task.backlog === true,\n\t\t\t).length,\n\t\t\topenCount: entry.rows.filter(\n\t\t\t\t(row) => row.kind === \"task\" && row.task.status === \"open\",\n\t\t\t).length,\n\t\t\ttotal: entry.rows.length,\n\t\t\trows: entry.rows.sort(inGroupOrder),\n\t\t}))\n\t\t.sort((a, b) => a.title.localeCompare(b.title, \"zh-Hans-CN\"));\n\treturn {\n\t\tmine: mineRows,\n\t\tgroups,\n\t\ttotal: groups.reduce((sum, group) => sum + group.rows.length, 0),\n\t\tallCounts,\n\t};\n}\n\n/**\n * 已结案列表(统计 tab 用;首页不渲染已结案 ⇒ 这里只留数据面,供后续统计 tab 复用同一套筛选口径)。\n */\nexport function selectClosed(current: {\n\thistory: readonly HistoryRecord[];\n\tquery: Query;\n}): Row[] {\n\treturn current.history\n\t\t.filter((record) =>\n\t\t\thitKeyword(current.query.keyword, [\n\t\t\t\trecord.summary,\n\t\t\t\trecord.workpackage,\n\t\t\t\tdisplayName(record.owner_name, record.owner),\n\t\t\t\trecord.category,\n\t\t\t\t...(record.tags ?? []),\n\t\t\t]),\n\t\t)\n\t\t.map((record, index) => ({\n\t\t\tkind: \"closed\",\n\t\t\tkey: `${record.src ?? \"\"}:${record.time ?? \"\"}:${index}`,\n\t\t\trecord,\n\t\t}));\n}\n","/**\n * 数据面取数**单源**:所有 client → host 的 HTTP 都在这里,页面不许各写一份 fetch。\n *\n * 纪律:只做传输与形状校验,不造兜底假值(DSH 插件规则「数据真实」)——\n * 失败就抛,由调用方显示错误态;返回什么渲染什么。\n *\n * ⚠️ 必须带超时且 abort 要带 reason:一次挂起的请求会让面板永久停在「读取中」,\n * 而不带 reason 时浏览器把 error.message 填成「signal is aborted without reason」,\n * 看不出是超时(姊妹仓 2026-10-07 真机教训)。\n */\nimport type {\n\tBoardPayload,\n\tCloseHandoff,\n\tFilterOptions,\n\tHistoryRecord,\n\tTaskDetail,\n\tTrendPayload,\n} from \"./types\";\n\n/** host 路由前缀(全仓唯一;与 host/routes.ts 的 API_PREFIX 对应)。 */\nexport const API_PREFIX = \"api/task-ledger\";\n\nconst DEFAULT_TIMEOUT_MS = 8_000;\n/** 趋势端点读 history,比快路径慢一个量级(20 万条实测 4s+),超时单给。 */\nconst TREND_TIMEOUT_MS = 30_000;\n\n/**\n * 错误响应榨人话:host 路由(routes.ts)发的是 `{ error: \"...\" }`,那里的话是**能直接上界面的**\n * (带工作区名、python3 起不来之类的原文)。不带它界面上只剩「HTTP 500」,等于没报错。\n */\nexport function httpErrorMessage(status: number, body: string): string {\n\ttry {\n\t\tconst parsed = JSON.parse(body) as { error?: unknown };\n\t\tif (typeof parsed.error === \"string\" && parsed.error !== \"\")\n\t\t\treturn `HTTP ${status}:${parsed.error}`;\n\t} catch {\n\t\t/* 不是 JSON:走原文 */\n\t}\n\tconst text = body.trim().slice(0, 200);\n\treturn text === \"\"\n\t\t? `HTTP ${String(status)}`\n\t\t: `HTTP ${String(status)}:${text}`;\n}\n\n/** 带超时的 JSON 取数(相对路径,同源)。 */\nexport async function fetchJson<T>(\n\tpath: string,\n\tinit: RequestInit = {},\n\ttimeoutMs = DEFAULT_TIMEOUT_MS,\n): Promise<T> {\n\tconst controller = new AbortController();\n\tconst timer = setTimeout(() => {\n\t\tcontroller.abort(\n\t\t\tnew DOMException(`请求超时(${timeoutMs}ms 未响应)`, \"TimeoutError\"),\n\t\t);\n\t}, timeoutMs);\n\ttry {\n\t\tconst res = await fetch(`${API_PREFIX}${path}`, {\n\t\t\t...init,\n\t\t\tsignal: controller.signal,\n\t\t\tcache: \"no-store\",\n\t\t});\n\t\tif (!res.ok)\n\t\t\tthrow new Error(\n\t\t\t\thttpErrorMessage(res.status, await res.text().catch(() => \"\")),\n\t\t\t);\n\t\treturn (await res.json()) as T;\n\t} finally {\n\t\tclearTimeout(timer);\n\t}\n}\n\n/**\n * 首页快照(快路径:在办全量 + 统计 + 各工作区身份;**不含趋势**)。\n * `fresh` = 让 host 先清 1.5s 读缓存再算(手动刷新 / 首读都要最新,不吃上一屏的缓存)。\n */\nexport function fetchBoardSnapshot(\n\topts: { fresh?: boolean } = {},\n): Promise<BoardPayload> {\n\treturn fetchJson<BoardPayload>(`/board/snapshot${freshSuffix(opts)}`);\n}\n\n/**\n * 趋势(慢路径:近 8 周 + 四个自然周期,host 侧要读 history)。\n * 超时给得比默认宽:历史量大时读得久(实测 20 万条量级 4s+);\n * 旧宿主没有该端点 ⇒ 404,直接抛给调用方兜底,不阻塞列表。\n */\nexport function fetchTrend(\n\topts: { fresh?: boolean } = {},\n): Promise<TrendPayload> {\n\treturn fetchJson<TrendPayload>(\n\t\t`/board/trend${freshSuffix(opts)}`,\n\t\t{},\n\t\tTREND_TIMEOUT_MS,\n\t);\n}\n\n/** `?fresh=1` 只在真要最新值时带;不带就吃 host 的 1.5s 缓存。 */\nfunction freshSuffix(opts: { fresh?: boolean }): string {\n\treturn opts.fresh === true ? \"?fresh=1\" : \"\";\n}\n\n/** 已结案列表(服务端按窗口 / 标签 / 分页过滤)。 */\nexport function fetchHistory(params: {\n\tsince?: string;\n\tuntil?: string;\n\ttag?: string;\n\tlimit?: number;\n}): Promise<HistoryRecord[]> {\n\tconst query = new URLSearchParams();\n\tif (params.since !== undefined) query.set(\"since\", params.since);\n\tif (params.until !== undefined) query.set(\"until\", params.until);\n\tif (params.tag !== undefined && params.tag !== \"\")\n\t\tquery.set(\"tag\", params.tag);\n\tif (params.limit !== undefined) query.set(\"limit\", String(params.limit));\n\tconst suffix = query.toString();\n\treturn fetchJson<{ records: HistoryRecord[] }>(\n\t\t`/history${suffix === \"\" ? \"\" : `?${suffix}`}`,\n\t).then((body) => body.records ?? []);\n}\n\n/** 单条在办 + 过程文档正文(展开行用)。 */\nexport function fetchTaskDetail(\n\tworkspaceId: string,\n\ttaskId: string,\n): Promise<TaskDetail> {\n\tconst query = new URLSearchParams({ ws: workspaceId, id: taskId });\n\treturn fetchJson<TaskDetail>(`/task?${query.toString()}`);\n}\n\n/** 筛选项候选(在办全量 + 近 13 个月历史的去重 owner / category / tag)。 */\nexport function fetchFilters(): Promise<FilterOptions> {\n\treturn fetchJson<FilterOptions>(\"/filters\");\n}\n\n/**\n * 结束任务:请 host 起一个会话(首条 = 预置提示词 + 用户留言),返回 `sessionId` 供跳转。\n *\n * `message` 是用户在弹框里留的话(可空);`provider` / `model` 成对给 = 用用户选的模型,\n * 都不给 = 用宿主默认模型(只给一半会被 host 400 拒,不做猜测)。\n */\nexport function requestClose(body: {\n\tws: string;\n\tid: string;\n\tmessage: string;\n\tprovider?: string;\n\tmodel?: string;\n}): Promise<CloseHandoff> {\n\treturn fetchJson<CloseHandoff>(\"/close\", {\n\t\tmethod: \"POST\",\n\t\theaders: { \"content-type\": \"application/json\" },\n\t\tbody: JSON.stringify(body),\n\t});\n}\n\n/** 认领 / 释放的写结果;成功后由调用方自行刷新快照(host 已清该工作区读缓存)。 */\nexport interface TaskMutationResult {\n\treadonly ok: true;\n\t/** 写成功但同步(commit / push)没成功时的人话;同步正常时没有这个字段。 */\n\treadonly notice?: string;\n}\n\n/**\n * 认领:点一下即归当前用户(host 直跑脚本,不开会话)。\n * 只有 `open` 且无人认领才允许,忙时 host 回 500 + 人话(脚本原文)。\n */\nexport function requestClaim(body: {\n\tws: string;\n\tid: string;\n}): Promise<TaskMutationResult> {\n\treturn fetchJson<TaskMutationResult>(\"/claim\", {\n\t\tmethod: \"POST\",\n\t\theaders: { \"content-type\": \"application/json\" },\n\t\tbody: JSON.stringify(body),\n\t});\n}\n\n/** 释放:退回待认领(owner 清空),只许当前 owner 本人(host 侧脚本校验)。 */\nexport function requestRelease(body: {\n\tws: string;\n\tid: string;\n}): Promise<TaskMutationResult> {\n\treturn fetchJson<TaskMutationResult>(\"/release\", {\n\t\tmethod: \"POST\",\n\t\theaders: { \"content-type\": \"application/json\" },\n\t\tbody: JSON.stringify(body),\n\t});\n}\n","/**\n * 看板数据仓(client 侧**唯一**取数入口):浮标角标与整页共用同一份快照,\n * 谁先挂载谁触发首读;刷新按钮走同一个 `refresh()`,**不轮询**(2026-10-17 拍板:\n * 后端纯按需,刷新时机归前端 = 打开面板首读 + 手动刷新)。\n *\n * 消费方式:`useSyncExternalStore(boardSubscribe, boardSnapshot)`。\n * ⚠️ `getSnapshot` 必须返回**稳定引用**(每次新建对象会被判定为「一直在变」⇒ 无限重渲染),\n * 故只在真变了时才换 `state` 对象。\n */\nimport { fetchBoardSnapshot, fetchTrend } from \"./api\";\nimport type { BoardPayload, TrendPayload } from \"./types\";\n\n/** 范围:我的 / 全部工作区。 */\nexport type Scope = \"mine\" | \"all\";\n/** 状态档:进行中 = doing;积压 / 逾期 / 停滞 = host 按时间标记的 backlog / overdue / stale。 */\nexport type StatusFilter =\n\t| \"all\"\n\t| \"active\"\n\t| \"open\"\n\t| \"backlog\"\n\t| \"overdue\"\n\t| \"stale\";\n\nexport interface Query {\n\tscope: Scope;\n\t/** 「其他待办」的状态档过滤(segmented)。 */\n\tstatus: StatusFilter;\n\t/** 工作区 id;'' = 全部工作区(只作用于「我的待办」)。 */\n\tworkspace: string;\n\t/** 「我的待办」的标题搜索。 */\n\tkeyword: string;\n\t/** 「其他待办」的搜索(标题 / 执行人)。 */\n\tothersKeyword: string;\n}\n\nexport interface BoardState {\n\tstatus: \"loading\" | \"ready\" | \"error\";\n\tboard: BoardPayload | null;\n\terror: string | null;\n\tquery: Query;\n\t/** 手动刷新在途(按钮转圈 / 禁用)。 */\n\trefreshing: boolean;\n\t/** 趋势(慢路径,`/board/trend`):null = 还没回来 / 旧宿主没有该端点。 */\n\ttrend: TrendPayload | null;\n\t/** 趋势加载态:首屏不阻塞列表,图表区自己显示占位 / 兜底文案。 */\n\ttrendStatus: \"idle\" | \"loading\" | \"ready\" | \"error\";\n\ttrendError: string | null;\n}\n\nconst INITIAL_QUERY: Query = {\n\tscope: \"all\",\n\tstatus: \"all\",\n\tworkspace: \"\",\n\tkeyword: \"\",\n\tothersKeyword: \"\",\n};\n\nlet state: BoardState = {\n\tstatus: \"loading\",\n\tboard: null,\n\terror: null,\n\tquery: INITIAL_QUERY,\n\trefreshing: false,\n\ttrend: null,\n\ttrendStatus: \"idle\",\n\ttrendError: null,\n};\n\nconst listeners = new Set<() => void>();\n/** 首读只触发一次(谁先订阅谁触发),之后一律靠 `refresh()` / `setQuery()`。 */\nlet booted = false;\n/** 在途轮次:迟到的响应按 token 丢弃,避免旧结果盖新结果。 */\nlet runToken = 0;\n\nfunction emit(): void {\n\tfor (const listener of [...listeners]) listener();\n}\n\nfunction set(patch: Partial<BoardState>): void {\n\tstate = { ...state, ...patch };\n\temit();\n}\n\nexport function boardSnapshot(): BoardState {\n\treturn state;\n}\n\nexport function boardSubscribe(listener: () => void): () => void {\n\tlisteners.add(listener);\n\tif (!booted) {\n\t\tbooted = true;\n\t\tvoid refresh();\n\t}\n\treturn () => {\n\t\tlisteners.delete(listener);\n\t};\n}\n\n/**\n * 重读(2026-10-18 拆端点):**两段**——先快路径 `/board/snapshot`(只读在办,首屏立即可渲染),\n * 再慢路径 `/board/trend`(读 history,后台拉;迟到按 token 丢弃,不盖新快照)。\n * 趋势失败(含旧宿主 404)不阻塞列表:trendStatus 置 error,图表区显示兜底文案。\n * 两段都带 `fresh=1`:本函数只由首读与手动刷新触发,都要最新值(host 缓存清两次无害,清是全局的)。\n */\nexport async function refresh(): Promise<void> {\n\tconst token = ++runToken;\n\tset({ refreshing: true });\n\ttry {\n\t\tconst board = await fetchBoardSnapshot({ fresh: true });\n\t\tif (token !== runToken) return;\n\t\tset({\n\t\t\tstatus: \"ready\",\n\t\t\tboard,\n\t\t\terror: null,\n\t\t\ttrendStatus: \"loading\",\n\t\t\ttrendError: null,\n\t\t});\n\t} catch (error) {\n\t\tif (token !== runToken) return;\n\t\tset({\n\t\t\tstatus: \"error\",\n\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t});\n\t\treturn;\n\t} finally {\n\t\tif (token === runToken) set({ refreshing: false });\n\t}\n\ttry {\n\t\tconst trend = await fetchTrend({ fresh: true });\n\t\tif (token !== runToken) return;\n\t\tset({ trend, trendStatus: \"ready\", trendError: null });\n\t} catch (error) {\n\t\tif (token !== runToken) return;\n\t\tset({\n\t\t\ttrend: null,\n\t\t\ttrendStatus: \"error\",\n\t\t\ttrendError: error instanceof Error ? error.message : String(error),\n\t\t});\n\t}\n}\n\n/** 改筛选:全部在浏览器里完成(快照已含全部在办),不发请求。 */\nexport function setQuery(patch: Partial<Query>): void {\n\tset({ query: { ...state.query, ...patch } });\n}\n","/**\n * 客户端时间口径**单源**:补零 / 时刻串(本机时区)。\n * 解析失败按调用方给的兜底返回(不编造时间)。\n *\n * 2026-10-17 改版后首页不再做时间范围过滤(时间只作用于统计卡与趋势图,由 host 聚合)\n * ⇒ 原来的 `rangeToDates` / `withinRange` / `RangeKey` 一并删除;统计 tab 要做时间筛选时\n * 按当时口径在此重建,别处不许再写一份。\n */\nexport function pad2(value: number | string): string {\n\treturn String(value).padStart(2, \"0\");\n}\n\n/** ISO → `YYYY-MM-DD HH:mm`(`seconds: true` 时补 `:ss`);解析失败返回 `fallback`(缺省原串)。 */\nexport function formatDateTime(\n\tiso: string,\n\topts?: { seconds?: boolean; fallback?: string },\n): string {\n\tconst ms = Date.parse(iso);\n\tif (Number.isNaN(ms)) return opts?.fallback ?? iso;\n\tconst d = new Date(ms);\n\tconst base = `${d.getFullYear()}-${pad2(d.getMonth() + 1)}-${pad2(d.getDate())} ${pad2(d.getHours())}:${pad2(d.getMinutes())}`;\n\treturn opts?.seconds === true ? `${base}:${pad2(d.getSeconds())}` : base;\n}\n","/**\n * 语义 token 层:`--dtl-*`(dtl = dsh-task-ledger)。\n *\n * 规矩(docs/design/ui-style.md §三,2026-10-17 对齐 dispatch 表后收严):\n * - **只有本文件定义 `--dtl-*`**;其它文件一律 `var(--dtl-*)` 消费,不许直接写 `var(--dsw-*)`;\n * - 每个 token 都带兜底值 ⇒ 宿主升级换名时不炸(最坏退到兜底色,不会白屏);\n * - 明暗差异只写在本文件末尾的 `body[data-ds-dark-theme]` 段:能靠宿主 alias 表达的\n * 一律不写覆盖(alias 自己随主题变),只有「固定中性面 / 半透明底」这类 alias 表达不了的才进该段。\n * - **离散刻度**:圆角 4/8/12/16/20/28、间距 4/8/12/16、控件高 24/28/32、字号 11/12/13/14/16\n * ——业务文件不许出现 5/7/9px、不许自造高度档(要加档位改本文件)。\n *\n * 明暗判据 = `body[data-ds-dark-theme]`(宿主 0.2.0-rc.2 源码核实:启动脚本 toggleAttribute 写入)。\n * 插件**禁用** `prefers-color-scheme`(它跟系统、不跟用户在宿主里的选择)。\n * 因为判据是纯 CSS 选择器 ⇒ 宿主切主题即生效,**不需要 MutationObserver**。\n *\n * 挂载点 = `body`:插件界面(含将来 portal 到 body 的弹层)全在 body 内,零调用点成本。\n */\nexport const UI_TOKENS_CSS = `\nbody{\n /* ── 文字四档 + 反色面 ───────────────────────────────────────── */\n --dtl-fg:var(--dsw-alias-label-primary,#1f2328);\n --dtl-fg-2:var(--dsw-alias-label-secondary,#5c6370);\n --dtl-fg-3:var(--dsw-alias-label-tertiary,#767d87);\n --dtl-fg-4:var(--dsw-alias-label-caption,#9aa1ab);\n --dtl-fg-dim:var(--dsw-alias-label-dimmed,#b9bfc7);\n /* 反色面上的字(角标 / 实心钮):暗色下是 bluish-1000 ⇒ 用 -foreground 而非 -inverted */\n --dtl-fg-inverse:var(--dsw-alias-label-primary-foreground,#fff);\n\n /* ── 面 ──────────────────────────────────────────────────────── */\n --dtl-surface-1:var(--dsw-alias-bg-layer-1,#fff);\n --dtl-surface-2:var(--dsw-alias-bg-layer-2,#fff);\n --dtl-surface-base:var(--dsw-alias-bg-base,#fff);\n /* 「选中亮片」底盘(配 shadow-raised 用) */\n --dtl-surface-raised:var(--dsw-alias-bg-layer-1,#fff);\n /* 固定中性实面(自绘浮标 / 角标这类必须自己变的东西) */\n --dtl-solid:var(--dsw-static-neutral-00,#fff);\n --dtl-on-solid:var(--dsw-alias-label-primary,#1f2328);\n /* 斑马纹 / 次层面(浅色下近白、深色下深一档) */\n --dtl-plate:var(--dsw-static-neutral-50,#fafafa);\n /* 斑马纹:几乎贴着原色的一层(用户 2026-10-18:3% 还是太明显) */\n --dtl-zebra:color-mix(in srgb,var(--dtl-fg) 2%,transparent);\n --dtl-plate-hover:var(--dsw-static-neutral-100,#f5f5f5);\n /* 表头底:浅色比斑马纹再深一档(两者不能撞色) */\n --dtl-head-bg:var(--dsw-static-neutral-100,#f5f5f5);\n\n /* ── 描边四档(宿主真值 l1 4% / l2 10% / l3 12% / l4 16%)────── */\n --dtl-border-faint:var(--dsw-alias-border-l1,#0000000a);\n --dtl-border:var(--dsw-alias-border-l2,#0000001a);\n --dtl-border-strong:var(--dsw-alias-border-l3,#0000001f);\n --dtl-border-heavy:var(--dsw-alias-border-l4,#00000029);\n\n /* ── 语义色 ──────────────────────────────────────────────────── */\n /* 品牌「面」色:明色近黑、暗色近白(实心钮选中态即此),不是蓝 */\n --dtl-accent:var(--dsw-alias-brand-primary,#0f1115);\n /* 蓝色强调 / 选中 / 焦点一律走这条 */\n --dtl-business:var(--dsw-alias-state-business-primary,#3b5bdb);\n --dtl-success:var(--dsw-alias-state-success-primary,#22c55e);\n /* ⚠️ 宿主是 state-warn(不是 state-warning,后者无此定义) */\n --dtl-warning:var(--dsw-alias-state-warn-primary,#f59e0b);\n --dtl-danger:var(--dsw-alias-state-error-primary,#ec1313);\n /* 逾期橙:在「积压黄」与「停滞红」之间再取一档(语义阶梯 灰→黄→橙→红),\n 宿主没有现成的橙 token ⇒ 用 warn + error 两色现算,主题一换自动跟随 */\n --dtl-overdue:color-mix(in srgb,var(--dtl-warning) 55%,var(--dtl-danger));\n --dtl-link:var(--dsw-alias-link,#3b5bdb);\n /* 语义色实面上的字(角标 / 实心提示):红绿黄都是中调 ⇒ 白字两个主题都可读 */\n --dtl-on-signal:#fff;\n /* 语义色浅底:color-mix 现算 ⇒ 跟随宿主 alias,主题一换自动成立 */\n --dtl-business-soft:color-mix(in srgb,var(--dtl-business) 14%,transparent);\n /* 他人任务的 doing 色:比「我的」蓝灰一档(用户 2026-10-17:要和我的蓝区分) */\n --dtl-business-dim:color-mix(in srgb,var(--dtl-business) 55%,var(--dtl-fg-3));\n /* 组标题底:左深蓝竖条后面的那层**浅蓝**(用户 2026-10-18 照参考图) */\n --dtl-group-head-bg:#eaf1ff;\n --dtl-success-soft:color-mix(in srgb,var(--dtl-success) 8%,transparent);\n --dtl-warning-soft:color-mix(in srgb,var(--dtl-warning) 8%,transparent);\n --dtl-danger-soft:color-mix(in srgb,var(--dtl-danger) 8%,transparent);\n\n /* ── 交互底 ──────────────────────────────────────────────────── */\n --dtl-hover:var(--dsw-alias-interactive-bg-hover,rgba(38,49,72,.06));\n --dtl-active:var(--dsw-alias-interactive-bg-active,#2631481a);\n /* 卡 / 行 hover 高亮:淡蓝(灰高亮在卡底上几乎看不出来) */\n --dtl-card-hover:rgba(37,99,235,.07);\n /* 展开行底:带透明度的蓝,透出卡片底色(灰底跟斑马纹分不出来) */\n --dtl-open-bg:rgba(37,99,235,.10);\n --dtl-open-bg-soft:rgba(37,99,235,.05);\n /* chip / 标签小底板:浅色下要看得见 ⇒ 掺 7% 近黑;hover 加倍 */\n --dtl-chip-bg:rgba(15,15,15,.07);\n --dtl-chip-bg-hover:rgba(15,15,15,.14);\n /* 图表「新增」柱:**实底**中性灰。半透明底压在卡上会发糊(用户 2026-10-17:「模模糊糊」) */\n --dtl-chart-created:var(--dsw-static-neutral-300,#d4d4d8);\n /* 图表「没完成」柱:醒目琥珀,与蓝(完成)/ 灰(新增)区分(host 无此件,fallback 兜底) */\n --dtl-chart-remaining:var(--dsw-static-amber-400,#f59e0b);\n\n /* ── 圆角(宿主真值 4/8/12/16/20/28)──────────────────────────── */\n --dtl-radius-xs:var(--dsw-radius-xs,4px);\n --dtl-radius-sm:var(--dsw-radius-sm,8px);\n --dtl-radius-md:var(--dsw-radius-md,12px);\n --dtl-radius-lg:var(--dsw-radius-lg,16px);\n --dtl-radius-xl:var(--dsw-radius-xl,20px);\n --dtl-radius-panel:var(--dsw-radius-panel,28px);\n\n /* ── 间距四拍(只许这四档)────────────────────────────────────── */\n --dtl-space-1:4px;\n --dtl-space-2:8px;\n --dtl-space-3:12px;\n --dtl-space-4:16px;\n\n /* ── 控件高度:离散三档(调用点不许自定义高度)────────────────── */\n --dtl-control-h-sm:24px;\n --dtl-control-h-md:28px;\n --dtl-control-h-lg:32px;\n\n /* ── 字号 / 行高(直绑宿主字号族 11/12/13/14/16)──────────────── */\n --dtl-font-xs:var(--dsw-font-xxxs-11-font-size,11px);\n --dtl-font-sm:var(--dsw-font-xxs-12-font-size,12px);\n --dtl-font-md:var(--dsw-font-xs-13-font-size,13px);\n --dtl-font-lg:var(--dsw-font-s-14-font-size,14px);\n --dtl-font-xl:var(--dsw-font-base-16-font-size,16px);\n --dtl-line-xs:var(--dsw-font-xxxs-11-line-height,14px);\n --dtl-line-sm:var(--dsw-font-xxs-12-line-height,18px);\n --dtl-line-md:var(--dsw-font-xs-13-line-height,20px);\n --dtl-line-lg:var(--dsw-font-s-14-line-height,22px);\n --dtl-line-xl:var(--dsw-font-base-16-line-height,24px);\n --dtl-font-mono:var(--ds-font-family-code,monospace);\n /* 统计卡主数字:宿主字号族最大 16px,看板主数字要更大 ⇒ 单开一档(别处不许直接写 px) */\n --dtl-font-stat:26px;\n\n /* ── 投影 / 动效 / 层级 ──────────────────────────────────────── */\n --dtl-shadow-1:var(--dsw-elevation-soft,0 4px 16px 0 #00000008);\n --dtl-shadow-raised:var(--dsw-elevation-soft,0 4px 16px 0 #00000008);\n --dtl-shadow-2:var(--dsw-shadow-lv3,0 12px 32px 0 #00000014);\n --dtl-dur:var(--ds-transition-duration,.2s);\n --dtl-dur-fast:var(--ds-transition-duration-fast,.12s);\n --dtl-ease:var(--ds-ease-in-out,cubic-bezier(.4,0,.2,1));\n --dtl-z-badge:20;\n}\n\n/* ── 明暗差异的唯一落点 ─────────────────────────────────────────\n 只放 alias 表达不了的固定面 / 半透明底;颜色若能靠 alias 自动跟随,一律不写在这里。 */\nbody[data-ds-dark-theme]{\n --dtl-solid:var(--dsw-static-neutral-900,#0f0f0f);\n --dtl-on-solid:var(--dsw-static-neutral-00,#fff);\n --dtl-plate:var(--dsw-static-neutral-850,#212123);\n --dtl-zebra:color-mix(in srgb,var(--dtl-fg) 2.5%,transparent);\n --dtl-plate-hover:var(--dsw-static-neutral-800,#292929);\n /* 暗色表头反过来:比卡片面亮、比斑马纹浅一档 */\n --dtl-head-bg:var(--dtl-surface-2);\n /* 暗色下蓝要更亮、透明度更高才压得住深底 */\n --dtl-open-bg:rgba(96,165,250,.18);\n --dtl-open-bg-soft:rgba(96,165,250,.08);\n --dtl-card-hover:rgba(96,165,250,.13);\n /* 暗色 chip 底板反过来掺白 */\n --dtl-chip-bg:rgba(255,255,255,.08);\n --dtl-chip-bg-hover:rgba(255,255,255,.16);\n --dtl-chart-created:var(--dsw-static-neutral-600,#525252);\n --dtl-chart-remaining:var(--dsw-static-amber-500,#fbbf24);\n /* 语义色浅底在深色下压到 5%(8% 在深底上偏重) */\n --dtl-business-soft:color-mix(in srgb,var(--dtl-business) 12%,transparent);\n --dtl-business-dim:color-mix(in srgb,var(--dtl-business) 55%,var(--dtl-fg-3));\n /* 组标题底(暗):**实色**蓝(参考图不是半透明叠加出来的) */\n --dtl-group-head-bg:#1e3a5f;\n --dtl-success-soft:color-mix(in srgb,var(--dtl-success) 5%,transparent);\n --dtl-warning-soft:color-mix(in srgb,var(--dtl-warning) 5%,transparent);\n --dtl-danger-soft:color-mix(in srgb,var(--dtl-danger) 5%,transparent);\n}\n`;\n\n/**\n * 控件皮肤(L2):**一类控件唯一实现**,抄 dispatch 表 controls-css 的规矩——\n * 只消费 var(--dtl-*),一个颜色 / 尺寸 / 圆角 / 字号字面量都不许出现;\n * 高度只取三档,有边框的变体用 1px 真边框 + 内部 padding 补回 ⇒ 有边 / 无边同高。\n */\nexport const UI_CONTROLS_CSS = `\n/* ── 分段控件(滑动块)────────────────────────────────────────────\n 结构一套 + 两个受控轴:size(sm|md|lg) × variant(default|inset)。\n 变体只覆盖两个颜色变量(--seg-track / --seg-thumb),结构 / 尺寸 / 交互零重复。 */\n.dtl-seg{display:inline-flex;align-items:center;gap:2px;padding:2px;border-radius:var(--dtl-radius-md);background:var(--seg-track);}\n.dtl-seg--default{--seg-track:var(--dtl-surface-2);--seg-thumb:var(--dtl-surface-raised);border:1px solid var(--dtl-border);}\n.dtl-seg--inset{--seg-track:var(--dtl-hover);--seg-thumb:var(--dtl-surface-raised);border:0;padding:3px;}\n.dtl-seg__item{appearance:none;display:inline-flex;align-items:center;gap:4px;box-sizing:border-box;\n height:calc(var(--dtl-control-h-sm) - 6px);padding:0 12px;border:0;border-radius:var(--dtl-radius-sm);\n background:transparent;color:var(--dtl-fg-2);font-family:inherit;font-size:var(--dtl-font-sm);line-height:var(--dtl-line-sm);\n font-weight:400;white-space:nowrap;cursor:pointer;\n transition:color var(--dtl-dur-fast) var(--dtl-ease),background-color var(--dtl-dur-fast) var(--dtl-ease),box-shadow var(--dtl-dur-fast) var(--dtl-ease);}\n.dtl-seg--md .dtl-seg__item{height:calc(var(--dtl-control-h-md) - 6px);}\n.dtl-seg--lg .dtl-seg__item{height:calc(var(--dtl-control-h-lg) - 6px);}\n.dtl-seg__item:hover:not([aria-pressed='true']):not(:disabled){color:var(--dtl-fg);}\n.dtl-seg__item[aria-pressed='true']{background:var(--seg-thumb);box-shadow:var(--dtl-shadow-raised);color:var(--dtl-fg);font-weight:600;}\n.dtl-seg__item:focus-visible{outline:2px solid var(--dtl-business);outline-offset:-2px;}\n.dtl-seg__item:disabled{cursor:default;opacity:.4;}\n/* 段内计数(如「待认领 3」):**纯文字,无底、无边、无圆角**(用户 2026-10-18:圆圈取了、字再小点)。\n 类名用 num 而不是旧 badge —— 万一宿主 DOM 里残留旧版 .dtl-seg__badge 圆圈规则,也匹配不中;0 不渲染 */\n.dtl-seg__num{display:inline;flex:none;margin-left:3px;padding:0;border:0;border-radius:0;\n background:none;color:var(--dtl-fg-3);font-size:10px;line-height:1;font-weight:400;font-variant-numeric:tabular-nums;}\n\n/* ── 按钮 / 图标钮 ───────────────────────────────────────────────\n 与 Segmented 同一条高度纪律;variant 只换颜色,结构 / 尺寸 / 交互只此一份。 */\n.dtl-btn{appearance:none;display:inline-flex;align-items:center;justify-content:center;gap:var(--dtl-space-1);\n box-sizing:border-box;border:1px solid transparent;border-radius:var(--dtl-radius-md);\n background:transparent;color:var(--dtl-fg);font-family:inherit;font-weight:500;white-space:nowrap;cursor:pointer;\n transition:background-color var(--dtl-dur-fast) var(--dtl-ease),border-color var(--dtl-dur-fast) var(--dtl-ease),color var(--dtl-dur-fast) var(--dtl-ease),opacity var(--dtl-dur-fast) var(--dtl-ease);}\n.dtl-btn--sm{height:var(--dtl-control-h-sm);padding:0 10px;font-size:var(--dtl-font-sm);line-height:var(--dtl-line-sm);}\n.dtl-btn--md{height:var(--dtl-control-h-md);padding:0 12px;font-size:var(--dtl-font-md);line-height:var(--dtl-line-md);}\n.dtl-btn--lg{height:var(--dtl-control-h-lg);padding:0 14px;font-size:var(--dtl-font-md);line-height:var(--dtl-line-md);}\n.dtl-btn--primary{background:var(--dtl-accent);color:var(--dtl-fg-inverse);}\n.dtl-btn--primary:hover:not(:disabled){opacity:.9;}\n.dtl-btn--outline{background:var(--dtl-surface-1);border-color:var(--dtl-border-strong);color:var(--dtl-fg);}\n.dtl-btn--outline:hover:not(:disabled){background:var(--dtl-hover);}\n.dtl-btn--ghost{color:var(--dtl-fg-2);}\n.dtl-btn--ghost:hover:not(:disabled){background:var(--dtl-hover);color:var(--dtl-fg);}\n.dtl-btn:focus-visible{outline:2px solid var(--dtl-business);outline-offset:2px;}\n.dtl-btn:disabled{cursor:default;opacity:.5;}\n.dtl-iconbtn{appearance:none;display:inline-flex;align-items:center;justify-content:center;box-sizing:border-box;\n border:1px solid transparent;border-radius:var(--dtl-radius-sm);background:transparent;color:var(--dtl-fg-2);\n font-family:inherit;cursor:pointer;flex:none;\n transition:background-color var(--dtl-dur-fast) var(--dtl-ease),border-color var(--dtl-dur-fast) var(--dtl-ease),color var(--dtl-dur-fast) var(--dtl-ease),opacity var(--dtl-dur-fast) var(--dtl-ease);}\n.dtl-iconbtn--sm{width:var(--dtl-control-h-sm);height:var(--dtl-control-h-sm);font-size:var(--dtl-font-sm);}\n.dtl-iconbtn--md{width:var(--dtl-control-h-md);height:var(--dtl-control-h-md);font-size:var(--dtl-font-md);}\n.dtl-iconbtn--lg{width:var(--dtl-control-h-lg);height:var(--dtl-control-h-lg);font-size:var(--dtl-font-md);}\n.dtl-iconbtn--outline{background:var(--dtl-surface-1);border-color:var(--dtl-border);color:var(--dtl-fg-2);}\n.dtl-iconbtn:hover:not(:disabled){background:var(--dtl-hover);color:var(--dtl-fg);}\n.dtl-iconbtn:focus-visible{outline:2px solid var(--dtl-business);outline-offset:1px;}\n.dtl-iconbtn:disabled{cursor:default;opacity:.4;}\n\n/* ── 输入 / 搜索框 / 下拉 ──────────────────────────────────────── */\n.dtl-input{box-sizing:border-box;width:100%;border:1px solid var(--dtl-border);border-radius:var(--dtl-radius-md);\n background:var(--dtl-surface-1);color:var(--dtl-fg);font-family:inherit;outline:none;\n transition:border-color var(--dtl-dur-fast) var(--dtl-ease),box-shadow var(--dtl-dur-fast) var(--dtl-ease);}\n.dtl-input--sm{height:var(--dtl-control-h-sm);padding:0 8px;font-size:var(--dtl-font-sm);line-height:var(--dtl-line-sm);}\n.dtl-input--md{height:var(--dtl-control-h-md);padding:0 10px;font-size:var(--dtl-font-md);line-height:var(--dtl-line-md);}\n.dtl-input--lg{height:var(--dtl-control-h-lg);padding:0 12px;font-size:var(--dtl-font-md);line-height:var(--dtl-line-md);}\n.dtl-input::placeholder{color:var(--dtl-fg-dim);}\n.dtl-input:focus{border-color:var(--dtl-business);box-shadow:0 0 0 1px var(--dtl-business);}\n.dtl-input:disabled{cursor:default;opacity:.5;}\n/* 原生 select: appearance:none + 自绘箭头 ⇒ 与输入框同宗(宿主没有廉价下拉件) */\n.dtl-select{appearance:none;-webkit-appearance:none;box-sizing:border-box;\n border:1px solid var(--dtl-border);border-radius:var(--dtl-radius-md);background:var(--dtl-surface-1);color:var(--dtl-fg);\n font-family:inherit;outline:none;cursor:pointer;\n background-image:url(\"data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23767d87' stroke-width='1.5'><path d='M4 6.5 8 10.5 12 6.5'/></svg>\");\n background-repeat:no-repeat;background-position:right 8px center;background-size:14px;\n transition:border-color var(--dtl-dur-fast) var(--dtl-ease),box-shadow var(--dtl-dur-fast) var(--dtl-ease);}\n.dtl-select--sm{height:var(--dtl-control-h-sm);padding:0 26px 0 8px;font-size:var(--dtl-font-sm);line-height:var(--dtl-line-sm);}\n.dtl-select--md{height:var(--dtl-control-h-md);padding:0 26px 0 10px;font-size:var(--dtl-font-md);line-height:var(--dtl-line-md);}\n.dtl-select--lg{height:var(--dtl-control-h-lg);padding:0 26px 0 12px;font-size:var(--dtl-font-md);line-height:var(--dtl-line-md);}\n.dtl-select:focus{border-color:var(--dtl-business);box-shadow:0 0 0 1px var(--dtl-business);}\n.dtl-select:disabled{cursor:default;opacity:.5;}\n\n/* ── 卡 / chip / 空态 / 列表行(业务壳,皮肤仍只消费 token)────── */\n.dtl-card{background:var(--dtl-surface-1);border:1px solid var(--dtl-border);border-radius:var(--dtl-radius-md);\n transition:background-color var(--dtl-dur-fast) var(--dtl-ease);}\n.dtl-card--clickable{cursor:pointer;text-align:left;font:inherit;color:inherit;width:100%;}\n.dtl-card--clickable:hover{background:var(--dtl-card-hover);}\n.dtl-card--clickable[data-active='true']{border-color:var(--dtl-business);}\n.dtl-card--clickable:focus-visible{outline:2px solid var(--dtl-business);outline-offset:1px;}\n.dtl-chip{display:inline-flex;align-items:center;gap:4px;height:20px;padding:0 8px;border-radius:var(--dtl-radius-sm);\n background:var(--dtl-chip-bg);color:var(--dtl-fg-2);font-size:var(--dtl-font-xs);line-height:var(--dtl-line-xs);white-space:nowrap;}\n.dtl-row{display:flex;align-items:center;gap:var(--dtl-space-2);width:100%;box-sizing:border-box;\n padding:var(--dtl-space-2) var(--dtl-space-3);border:0;border-bottom:1px solid var(--dtl-border-faint);\n background:transparent;font:inherit;color:inherit;text-align:left;cursor:pointer;\n transition:background-color var(--dtl-dur-fast) var(--dtl-ease);}\n.dtl-row:hover{background:var(--dtl-card-hover);}\n.dtl-row:focus-visible{outline:2px solid var(--dtl-business);outline-offset:-2px;}\n.dtl-row[data-open='true']{background:var(--dtl-open-bg);}\n.dtl-row-body{padding:var(--dtl-space-2) var(--dtl-space-3) var(--dtl-space-3);border-bottom:1px solid var(--dtl-border-faint);\n background:var(--dtl-open-bg-soft);font-size:var(--dtl-font-md);}\n.dtl-ellipsis{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}\n\n@media (prefers-reduced-motion: reduce){\n .dtl-seg__item,.dtl-btn,.dtl-iconbtn,.dtl-input,.dtl-select,.dtl-card,.dtl-row{transition:none;}\n}\n`;\n","/**\n * UI 基础层:样式单源 + 共用元件(**一类控件只有一份实现**)。\n *\n * 纪律(用户 2026-10-17「样式与方法一律抽象,不要反复重写」;形态抄本机\n * `dsh-task-dispatch-table` 的 `ui/tokens.ts` + `ui/controls-css.ts` + `ui/*.tsx`):\n * 1. **样式**:颜色 / 圆角 / 字号 / 高度一律 `var(--dtl-*)`(定义只在 tokens.ts),\n * 业务文件不许再写第二份 `var(--dsw-*)`、不许自造 `--dtl-*`、不许自造高度档;\n * 2. **元件**:分段 / 按钮 / 图标钮 / 输入 / 下拉 / 卡 / chip / 空态 / 图表各一份,\n * 页面与浮标共用。官方 primitives 只留「官方做得更好」的(StateDot / MarkdownText / 图标)。\n */\n\nimport { Tooltip } from \"@deepseek-ai/dsh-client-ui-primitives\";\nimport {\n\ttype ChangeEvent,\n\ttype CSSProperties,\n\tcreateElement as h,\n\ttype ReactNode,\n\tuseState,\n} from \"react\";\nimport { UI_CONTROLS_CSS, UI_TOKENS_CSS } from \"./tokens\";\n\n/** 基础层样式(tokens + 控件皮肤;幂等注入)。 */\nconst UI_BASE_CSS = `\n/* 统计卡:可点、hover 淡蓝、选中蓝描边 */\n.dtl-stat{display:flex;flex-direction:column;gap:var(--dtl-space-1);\n padding:var(--dtl-space-3) var(--dtl-space-4);text-align:left;}\n.dtl-stat__value{font-size:var(--dtl-font-stat);font-weight:600;line-height:1.15;font-variant-numeric:tabular-nums;}\n.dtl-stat__hint{font-size:var(--dtl-font-xs);line-height:var(--dtl-line-xs);color:var(--dtl-fg-3);}\n\n/* 列表行:分组标题头仍走 .dtl-row-head(可点折叠);任务行走 .dtl-taskrow(两行式,不可点) */\n.dtl-row-head{display:flex;align-items:center;gap:var(--dtl-space-2);\n width:100%;padding:var(--dtl-space-2) var(--dtl-space-3);border:0;background:transparent;\n color:inherit;font:inherit;text-align:left;cursor:pointer;\n transition:background-color var(--dtl-dur-fast) var(--dtl-ease);}\n.dtl-row-head:hover{background:var(--dtl-card-hover);}\n.dtl-row-head:focus-visible{outline:2px solid var(--dtl-business);outline-offset:-2px;}\n\n/* 其他待办 = **一组一张表**(用户 2026-10-18 照参考图 Stripe Payments:Pending / Archived /\n Completed 各一组):组标题是**独立一行**——透明无底、远离上一组、贴近自己的表,\n 文字加粗放大;表体照旧(行下一条线 + 极浅斑马纹)。 */\n/* 组与组**零外距**、连体(用户 2026-10-18:上间距去掉,和上面连在一起) */\n.dtl-group{margin-bottom:0;}\n/* 组标题(照参考图):**左侧深蓝竖条 + 浅蓝底(实色)**;行高保持(≈42px);\n 工作区名稍小一号(14px);上缘无边 */\n.dtl-group__head{position:relative;display:flex;align-items:center;gap:8px;width:100%;box-sizing:border-box;\n padding:10px var(--dtl-space-3);border:0;border-left:5px solid var(--dtl-business);\n border-radius:0;background:var(--dtl-group-head-bg);\n color:inherit;font:inherit;text-align:left;cursor:pointer;}\n/* 下缘那条线**绝不用 border 画**:border-left(5px) 与 border-bottom(1px) 在左下角\n 按 miter 斜接,会切出一个斜缺角(用户 2026-10-18 实锤,不是视觉误差)⇒ 改用伪元素\n 独立 1px;定位基于 padding box ⇒ 自动从竖条内缘起笔,竖条保持整直。 */\n.dtl-group__head::after{content:'';position:absolute;left:0;right:0;bottom:0;height:1px;\n background:var(--dtl-border-faint);pointer-events:none;}\n.dtl-group__name{font-size:var(--dtl-font-lg);font-weight:700;line-height:var(--dtl-line-lg);color:var(--dtl-fg);}\n.dtl-group__stats{font-size:var(--dtl-font-xs);color:var(--dtl-fg-2);white-space:nowrap;}\n/* 组标题标识:官方文件夹图标(展开=开、收起=合);图标缺席时回落成竖线 */\n.dtl-group__bar{width:3px;height:14px;flex:none;border-radius:2px;background:var(--dtl-business);}\n/* 表格行(.dtl-orow):**零重用**「我的待办」卡片基类——无框、无圆角、无外边距,\n 一行 = 一条底部分隔线 + 极浅斑马纹(用户 2026-10-18:一行一格,不是一块一块的框) */\n.dtl-orow{padding:13px var(--dtl-space-3);border-bottom:1px solid var(--dtl-border-faint);}\n/* 斑马纹落在 2、4、6 行(用户 2026-10-18:原来 1、3、5 看着像从第一行就开始断层) */\n.dtl-orow:nth-of-type(even){background:var(--dtl-zebra);}\n.dtl-orow:hover{background:var(--dtl-card-hover);}\n.dtl-orow__row{display:flex;align-items:center;gap:12px;}\n.dtl-orow__title{display:flex;align-items:baseline;gap:6px;min-width:0;}\n.dtl-orow__name{font-size:var(--dtl-font-md);font-weight:500;line-height:var(--dtl-line-md);min-width:0;}\n/* 第二行:状态标签 + #标签(与标题行间距拉开,用户 2026-10-18;状态位与执行人**互换**后,\n 状态搬到这里、且永远有 ⇒ 这一行不再有「空一排」的情况) */\n.dtl-orow__tags{display:flex;align-items:center;gap:var(--dtl-space-2);margin-top:7px;min-width:0;}\n/* 列:任务(弹性)/ 执行人 / 右侧槽(创建信息 ⇄ 操作钮) */\n.dtl-tcell{min-width:0;}\n.dtl-tcell--title{flex:1 1 auto;}\n/* 执行人列(原状态列,用户 2026-10-18 互换):稍放宽一档(用户 2026-10-19:原来有点挤),\n 20 字的名字能基本摆全;再长由标签自己的省略号兜住,不许溢出压到右边的槽 */\n.dtl-tcell--status{flex:none;width:136px;}\n.dtl-tcell--status .dtl-tag{max-width:100%;}\n/* 悬停:**创建信息整条让位给操作钮**(用户 2026-10-18:不要「掉掉时分秒」那种半吊子,\n 要整条换掉)。两个都**常驻布局**(visibility 切换、不用 display),格子宽度 = 两者较宽的\n 那个 ⇒ hover 时行宽不变、**页面不跳**(跳了执行人的悬停提示就跟着飘) */\n.dtl-orow__slot{display:grid;align-items:center;justify-items:end;flex:none;\n font-size:var(--dtl-font-xs);color:var(--dtl-fg-3);white-space:nowrap;font-variant-numeric:tabular-nums;}\n.dtl-orow__slot>*{grid-area:1/1;}\n.dtl-orow__created{visibility:visible;}\n.dtl-orow__actions{visibility:hidden;display:flex;align-items:center;gap:6px;}\n.dtl-orow:hover .dtl-orow__created{visibility:hidden;}\n.dtl-orow:hover .dtl-orow__actions{visibility:visible;}\n/* 「查看」钮在表格行里也要常驻布局(display:none 会不算宽度 ⇒ hover 一出就又把行撑开) */\n.dtl-orow .dtl-viewbtn{display:inline-flex;visibility:hidden;}\n.dtl-orow:hover .dtl-viewbtn{visibility:visible;}\n/* 行首状态圆点:灰=待认领 / 浅蓝=进行中(比「我的」蓝灰一档)/ 黄=积压 / 橙=逾期 / 红=停滞;\n 6px(用户 2026-10-18:8px 太大) */\n.dtl-dot{display:inline-block;width:6px;height:6px;flex:none;border-radius:50%;}\n.dtl-dot--doing{background:var(--dtl-business-dim);}\n.dtl-dot--backlog{background:var(--dtl-warning);}\n.dtl-dot--overdue{background:var(--dtl-overdue);}\n.dtl-dot--stale{background:var(--dtl-danger);}\n.dtl-dot--open,.dtl-dot--closed{background:var(--dtl-fg-3);}\n\n/* 「查看」钮:与行内动作钮(.dtl-minibtn)同款皮肤、**正方形(26×26,宽=高)**、\n **默认不显、悬停才出来**(用户 2026-10-18:跟认领/继续那几个一起浮现) */\n.dtl-viewbtn{position:relative;display:none;align-items:center;justify-content:center;gap:5px;\n flex:none;width:26px;height:26px;padding:0;border:1px solid var(--dtl-border);\n border-radius:var(--dtl-radius-sm);background:var(--dtl-surface-1);color:var(--dtl-fg-2);\n font:inherit;font-size:var(--dtl-font-sm);line-height:18px;white-space:nowrap;cursor:default;}\n.dtl-viewbtn:hover{border-color:var(--dtl-border-strong);color:var(--dtl-fg);}\n.dtl-taskrow__row:hover .dtl-viewbtn,.dtl-orow:hover .dtl-viewbtn{display:inline-flex;}\n\n/* 任务行 = 一张卡(样式照抄 dispatch-table TaskCard:surface-1 底 + 1px 边框 + 左缘状态条;\n hover 只亮主行;右侧 时间⇄按钮排 互换) */\n.dtl-taskrow{background:var(--dtl-surface-1);border:1px solid var(--dtl-border);\n border-radius:var(--dtl-radius-sm);margin-bottom:10px;}\n.dtl-taskrow__row{display:flex;align-items:center;gap:12px;padding:12px 14px;border-radius:inherit;\n transition:background-color var(--dtl-dur-fast) var(--dtl-ease);}\n.dtl-taskrow__row:hover{background:var(--dtl-card-hover);}\n\n/* 状态条:贴卡片左缘、与正文两行等高的竖向色条(dispatch StatusRail 同款 6×36) */\n.dtl-rail{display:inline-block;width:6px;height:36px;flex:none;border-radius:var(--dtl-radius-xs);}\n.dtl-rail--doing{background:var(--dtl-business);}\n.dtl-rail--backlog{background:var(--dtl-warning);}\n.dtl-rail--overdue{background:var(--dtl-overdue);}\n.dtl-rail--stale{background:var(--dtl-danger);}\n.dtl-rail--open,.dtl-rail--closed{background:var(--dtl-fg-3);}\n\n/* 第一行:标题(上来就是标题)+ [YYYY-MM-DD 创建] 灰徽 + 异常 pill(baseline 对齐,dispatch 同款) */\n.dtl-taskrow__l1{display:flex;align-items:baseline;gap:6px;min-width:0;}\n.dtl-taskrow__title{font-size:var(--dtl-font-lg);font-weight:600;line-height:var(--dtl-line-md);min-width:0;flex:0 1 auto;}\n.dtl-taskrow__stamp{flex:none;font-size:var(--dtl-font-xs);color:var(--dtl-fg-3);white-space:nowrap;\n font-variant-numeric:tabular-nums;}\n/* 第二行小字:工作区 · #标签(行距拉开,用户 2026-10-17:第一二行别贴着) */\n.dtl-taskrow__l2{display:flex;align-items:center;gap:var(--dtl-space-2);margin-top:6px;\n font-size:var(--dtl-font-sm);color:var(--dtl-fg-2);min-width:0;}\n/* 右侧灰字:2026-10-17 开始丨已进行 12 天(用户 2026-10-17:不要蓝,一行灰字) */\n.dtl-taskrow__when{flex:none;font-size:var(--dtl-font-xs);color:var(--dtl-fg-3);white-space:nowrap;\n font-variant-numeric:tabular-nums;}\n.dtl-taskrow__actions{display:none;flex:none;gap:6px;}\n.dtl-taskrow__row:hover .dtl-taskrow__when{display:none;}\n.dtl-taskrow__row:hover .dtl-taskrow__actions{display:inline-flex;}\n\n/* 标签(用户 2026-10-18):状态 / 执行人 / #标签 **共用一枚件**,只换色调。\n 最大宽度 20ch(≈10 个中文或 20 个字符)⇒ 名字上限 20 字;超出**省略号(3 个点)**,\n 悬停把全名补出来(用户 2026-10-19:不跑马灯了)。**没被截 ⇒ 悬停无反应**\n (提示由 Tag 元件按实际宽度决定挂不挂,这里只管裁切)。 */\n.dtl-tag{display:inline-block;flex:none;max-width:20ch;padding:0 6px;border-radius:999px;\n background:var(--dtl-chip-bg);color:var(--dtl-fg-3);font-size:10px;line-height:16px;\n white-space:nowrap;overflow:hidden;text-overflow:ellipsis;vertical-align:middle;}\n/* 状态四色 = **实心色块**(用户 2026-10-18:彩色字看不清 ⇒ 改色块 + 反色字):\n 待认领灰 / 进行中蓝 / 积压黄 / 逾期橙 / 停滞红(与行首圆点同色系)。\n 红黄蓝都是中调 ⇒ 白字两个主题都可读;灰块用「字色底 + 面色字」⇒ 明暗自动反过来 */\n.dtl-tag--open{background:var(--dtl-fg-3);color:var(--dtl-surface-1);font-weight:600;}\n.dtl-tag--doing{background:var(--dtl-business);color:var(--dtl-on-signal);font-weight:600;}\n.dtl-tag--backlog{background:var(--dtl-warning);color:var(--dtl-on-signal);font-weight:600;}\n.dtl-tag--overdue{background:var(--dtl-overdue);color:var(--dtl-on-signal);font-weight:600;}\n.dtl-tag--stale{background:var(--dtl-danger);color:var(--dtl-on-signal);font-weight:600;}\n/* 执行人:浅蓝底(与状态色区分:状态是「事怎么样」,人是「谁在做」) */\n.dtl-tag--person{background:var(--dtl-open-bg-soft);color:var(--dtl-fg-2);}\n/* 分区标题里的计数:与日期徽同款中括号小字(用户 2026-10-17);0 条不渲染 */\n.dtl-count{font-size:var(--dtl-font-xs);color:var(--dtl-fg-3);font-variant-numeric:tabular-nums;}\n\n/* 工作区徽标:只铺蓝底(用户 2026-10-17:描边框太抢 ⇒ 去掉;底色已提亮一档见 tokens.ts\n business-soft 8%→14% / 5%→12%),字色回正文。 */\n.dtl-wstag{flex:none;max-width:220px;padding:1px 8px;border-radius:var(--dtl-radius-sm);\n background:var(--dtl-business-soft);color:var(--dtl-fg);\n font-size:var(--dtl-font-xs);line-height:16px;white-space:nowrap;}\n\n/* 行内动作按钮(icon + 字,加大;悬停说明走官方 Tooltip,不在 CSS 里手搓浮层)。\n 样子先行,点击行为归「任务按钮与会话交接」任务 */\n.dtl-minibtn{display:inline-flex;align-items:center;gap:5px;padding:4px 12px;\n border:1px solid var(--dtl-border);border-radius:var(--dtl-radius-sm);\n background:var(--dtl-surface-1);color:var(--dtl-fg-2);font:inherit;font-size:var(--dtl-font-sm);\n line-height:18px;white-space:nowrap;cursor:default;}\n.dtl-minibtn:hover{border-color:var(--dtl-border-strong);color:var(--dtl-fg);}\n\n/* 空态:真空 = 虚线引导卡(用户 2026-10-18:**加高到 180px + 内容居中**;\n 它贴在滚动条最底下,太窄用户根本看不见) */\n.dtl-empty-guide{display:flex;flex-direction:column;align-items:center;justify-content:center;\n gap:var(--dtl-space-2);min-height:270px;padding:var(--dtl-space-4);text-align:center;\n border:1px dashed var(--dtl-border-strong);border-radius:var(--dtl-radius-md);background:transparent;}\n.dtl-empty-filtered{padding:var(--dtl-space-4) 0;color:var(--dtl-fg-3);font-size:var(--dtl-font-md)}\n\n/* 浮标角标:0→n 跳变时一次脉冲,不自动消失 */\n.dtl-badge{position:absolute;top:-2px;right:-2px;min-width:16px;height:16px;padding:0 4px;\n border-radius:8px;background:var(--dtl-danger);color:var(--dtl-on-signal);\n font-size:10px;line-height:16px;text-align:center;font-weight:600;}\n.dtl-badge[data-pulse=\"true\"]{animation:dtl-pulse 900ms var(--dtl-ease) 1}\n@keyframes dtl-pulse{0%{transform:scale(.6);opacity:.4}60%{transform:scale(1.15)}100%{transform:scale(1)}}\n\n/* 统计区整体:左 8 块(2 行 × 4 列)+ 右趋势图,参考图同款分栏。\n ⚠️ 列数写死 4 → 2,绝不给 3:3 列会排出 3+1 的非对称(用户 2026-10-17)。\n 两栏**完全等高**:cards 两行 minmax(0,1fr) 均分 + 卡 height:100% ⇒ 图表卡与左边一样高。 */\n/* 左 8 块略收窄、右图表略放宽(用户 2026-10-17:左再短一丢丢、右长一丢丢) */\n.dtl-stats{display:grid;grid-template-columns:minmax(0,1.7fr) minmax(0,1fr);gap:var(--dtl-space-3);align-items:stretch;}\n.dtl-stats__cards{display:grid;grid-auto-flow:column;grid-template-columns:repeat(4,minmax(0,1fr));grid-template-rows:repeat(2,minmax(0,1fr));\n gap:var(--dtl-space-3);}\n.dtl-stats__cards > .dtl-stat{height:100%;box-sizing:border-box;}\n@media (max-width:960px){.dtl-stats{grid-template-columns:minmax(0,1fr);}}\n@media (max-width:640px){.dtl-stats__cards{grid-template-columns:repeat(2,minmax(0,1fr));grid-template-rows:repeat(4,minmax(0,1fr));}}\n\n/* 「只看我的」小复选框(替掉右上角的分段切换) */\n.dtl-check{display:inline-flex;align-items:center;gap:5px;height:20px;margin-top:-2px;\n font-size:var(--dtl-font-xs);color:var(--dtl-fg-3);cursor:pointer;user-select:none;white-space:nowrap;}\n.dtl-check input{width:12px;height:12px;margin:0;accent-color:var(--dtl-business);cursor:pointer;}\n.dtl-check:hover{color:var(--dtl-fg-2);}\n\n/* 趋势分组柱状图:绘图区高度**随卡拉伸**(flex),柱 / 刻度 / 网格全用百分比 ⇒ 与卡等高 */\n.dtl-gchart-wrap{flex:1 1 auto;min-height:0;display:flex;flex-direction:column;padding-left:30px;padding-bottom:18px;}\n.dtl-gchart{position:relative;flex:1 1 auto;min-height:96px;border-bottom:1px solid var(--dtl-border);}\n.dtl-gchart__grid{position:absolute;left:0;right:0;border-top:1px solid var(--dtl-border-faint);pointer-events:none;}\n.dtl-gchart__ytick{position:absolute;left:-30px;width:26px;text-align:right;font-size:10px;line-height:12px;\n color:var(--dtl-fg-3);transform:translateY(50%);font-variant-numeric:tabular-nums;}\n.dtl-gchart__col{position:absolute;top:0;bottom:0;min-width:0;}\n/* ⚠️ pair 必须 top/bottom 双锚(或 height:100%):绝对定位 + 只给 bottom 时高度是 auto,\n 子元素的 height:% 没有可解析的包含块 ⇒ 整根柱子塌成 0(2026-10-17 真机教训:\n 改百分比柱高后「一个柱子都看不见,只剩数字」)。 */\n.dtl-gchart__pair{position:absolute;top:0;bottom:0;left:50%;transform:translateX(-50%);\n display:flex;align-items:flex-end;gap:1px;}\n/* 三柱:完成(蓝) / 没完成(琥珀) / 新增(灰),每根 5px、无圆角(用户 2026-10-17:太粗、不要圆弧) */\n.dtl-gchart__bar{width:5px;min-height:0;}\n.dtl-gchart__bar--done{background:var(--dtl-business);}\n.dtl-gchart__bar--remaining{background:var(--dtl-chart-remaining);}\n.dtl-gchart__bar--created{background:var(--dtl-chart-created);}\n/* hover:整列三根柱一起提亮(用户 2026-10-17:移上去应该两个都变色,不是只蓝的一根) */\n.dtl-gchart__col:hover .dtl-gchart__bar{filter:brightness(1.18);}\n.dtl-gchart__val{position:absolute;left:50%;transform:translateX(-50%);font-size:10px;line-height:12px;\n color:var(--dtl-fg-2);font-variant-numeric:tabular-nums;white-space:nowrap;}\n.dtl-gchart__label{position:absolute;left:0;right:0;bottom:-16px;text-align:center;\n font-size:10px;line-height:14px;color:var(--dtl-fg-3);white-space:nowrap;}\n/* hover 浮卡(参考图同款:日期 + 两个数;原生 title 太慢、长相不一) */\n.dtl-gchart__tip{position:absolute;top:0;z-index:2;min-width:104px;box-sizing:border-box;\n padding:6px 8px;border:1px solid var(--dtl-border);border-radius:var(--dtl-radius-sm);\n background:var(--dtl-surface-1);box-shadow:var(--dtl-shadow-2);\n font-size:var(--dtl-font-xs);line-height:var(--dtl-line-sm);color:var(--dtl-fg-2);pointer-events:none;}\n.dtl-gchart__tip b{display:block;color:var(--dtl-fg);font-weight:600;}\n.dtl-gchart__tip i{display:inline-block;width:8px;height:8px;border-radius:2px;margin-right:4px;}\n.dtl-gchart-legend{display:flex;align-items:center;gap:var(--dtl-space-3);font-size:var(--dtl-font-xs);color:var(--dtl-fg-2);}\n.dtl-gchart-legend i{display:inline-block;width:8px;height:8px;border-radius:2px;margin-right:4px;}\n\n/* 过程正文:宽度受限、长行折行 */\n.dtl-worklog{max-width:72ch;font-size:var(--dtl-font-md);line-height:1.6}\n`;\n\nconst STYLE_ID = \"dtl-ui-base\";\n\n/** 幂等注入 token 层 + 控件皮肤 + 基础层(面板与浮标谁先挂载都只注入一次)。\n * 已挂载时**就地比对刷新**:插件升级后宿主若复用旧面板 DOM,旧样式表会一直挂着,\n * 导致新版本样式不生效(用户 2026-10-18:0.0.31 装上了圆圈还在)—— 内容变了就原位替换,不必重启。 */\nexport function ensureUiBase(): void {\n\tif (typeof document === \"undefined\") return;\n\tconst css = `${UI_TOKENS_CSS}\\n${UI_CONTROLS_CSS}\\n${UI_BASE_CSS}`;\n\tconst existing = document.getElementById(STYLE_ID);\n\tif (existing !== null) {\n\t\tif (existing.textContent !== css) existing.textContent = css;\n\t\treturn;\n\t}\n\tconst style = document.createElement(\"style\");\n\tstyle.id = STYLE_ID;\n\tstyle.textContent = css;\n\tdocument.head.appendChild(style);\n}\n\n/* ── 分段控件 ─────────────────────────────────────────────────────── */\n\n/** 一段(一个可选值)。 */\nexport interface SegmentedItem<Value extends string = string> {\n\treadonly value: Value;\n\treadonly label: string;\n\t/** 段内角标数字;`undefined` 或 ≤0 不显示。 */\n\treadonly badge?: number;\n}\n\n/** 分段控件(单选):同一份结构 + size 轴;外观差异只由 variant 的两个颜色变量表达。 */\nexport function Segmented<Value extends string>(props: {\n\titems: readonly SegmentedItem<Value>[];\n\tvalue: Value;\n\tonChange: (next: Value) => void;\n\tsize?: \"sm\" | \"md\" | \"lg\";\n\tvariant?: \"default\" | \"inset\";\n\tlabel: string;\n\tid?: string;\n\tstyle?: CSSProperties;\n}): ReactNode {\n\tensureUiBase();\n\tconst size = props.size ?? \"md\";\n\tconst variant = props.variant ?? \"default\";\n\treturn h(\n\t\t\"div\",\n\t\t{\n\t\t\trole: \"group\",\n\t\t\t\"aria-label\": props.label,\n\t\t\tid: props.id,\n\t\t\tclassName: `dtl-seg dtl-seg--${variant} dtl-seg--${size}`,\n\t\t\tstyle: props.style,\n\t\t},\n\t\tprops.items.map((item) =>\n\t\t\th(\n\t\t\t\t\"button\",\n\t\t\t\t{\n\t\t\t\t\tkey: item.value,\n\t\t\t\t\ttype: \"button\",\n\t\t\t\t\tclassName: \"dtl-seg__item\",\n\t\t\t\t\t\"aria-pressed\": item.value === props.value,\n\t\t\t\t\tonClick: () => {\n\t\t\t\t\t\tprops.onChange(item.value);\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\titem.label,\n\t\t\t\titem.badge !== undefined && item.badge > 0\n\t\t\t\t\t? h(\"span\", { className: \"dtl-seg__num\" }, String(item.badge))\n\t\t\t\t\t: null,\n\t\t\t),\n\t\t),\n\t);\n}\n\n/* ── 按钮 / 图标钮 ────────────────────────────────────────────────── */\n\nexport function Button(props: {\n\tchildren?: ReactNode;\n\tonClick: () => void;\n\tvariant?: \"primary\" | \"outline\" | \"ghost\";\n\tsize?: \"sm\" | \"md\" | \"lg\";\n\ticon?: ReactNode;\n\tdisabled?: boolean;\n\ttitle?: string;\n}): ReactNode {\n\tensureUiBase();\n\treturn h(\n\t\t\"button\",\n\t\t{\n\t\t\ttype: \"button\",\n\t\t\tclassName: `dtl-btn dtl-btn--${props.variant ?? \"outline\"} dtl-btn--${props.size ?? \"md\"}`,\n\t\t\tdisabled: props.disabled === true,\n\t\t\ttitle: props.title,\n\t\t\tonClick: props.onClick,\n\t\t},\n\t\tprops.icon,\n\t\tprops.children,\n\t);\n}\n\nexport function IconButton(props: {\n\ticon: ReactNode;\n\tlabel: string;\n\tonClick: () => void;\n\tvariant?: \"plain\" | \"outline\";\n\tsize?: \"sm\" | \"md\" | \"lg\";\n\tdisabled?: boolean;\n\ttitle?: string;\n}): ReactNode {\n\tensureUiBase();\n\treturn h(\n\t\t\"button\",\n\t\t{\n\t\t\ttype: \"button\",\n\t\t\tclassName: `dtl-iconbtn dtl-iconbtn--${props.variant ?? \"plain\"} dtl-iconbtn--${props.size ?? \"md\"}`,\n\t\t\t\"aria-label\": props.label,\n\t\t\tdisabled: props.disabled === true,\n\t\t\ttitle: props.title ?? props.label,\n\t\t\tonClick: props.onClick,\n\t\t},\n\t\tprops.icon,\n\t);\n}\n\n/* ── 输入 / 下拉 / 搜索 ───────────────────────────────────────────── */\n\n/** 原生下拉(工作区 / 状态共用一份;宿主没有廉价下拉件 ⇒ 原生 + token 皮肤)。\n * `width` 定宽(px);只给 `minWidth` = 内容自适应但有下限(工作区名长短不一时用)。 */\nexport function Select<Value extends string>(props: {\n\tvalue: Value;\n\toptions: readonly { value: Value; label: string }[];\n\tonChange: (next: Value) => void;\n\tariaLabel: string;\n\t/** 定宽(px);不给就按内容。 */\n\twidth?: number;\n\t/** 最小宽度(px);内容自适应时的下限。 */\n\tminWidth?: number;\n\tsize?: \"sm\" | \"md\" | \"lg\";\n}): ReactNode {\n\tensureUiBase();\n\tconst size = props.size ?? \"md\";\n\tconst style: CSSProperties | undefined =\n\t\tprops.width === undefined\n\t\t\t? props.minWidth === undefined\n\t\t\t\t? undefined\n\t\t\t\t: { minWidth: `${props.minWidth}px` }\n\t\t\t: { width: `${props.width}px` };\n\treturn h(\n\t\t\"select\",\n\t\t{\n\t\t\tclassName: `dtl-select dtl-select--${size}`,\n\t\t\t\"aria-label\": props.ariaLabel,\n\t\t\tstyle,\n\t\t\tvalue: props.value,\n\t\t\tonChange: (event: ChangeEvent<HTMLSelectElement>) => {\n\t\t\t\tprops.onChange(event.target.value as Value);\n\t\t\t},\n\t\t},\n\t\tprops.options.map((option) =>\n\t\t\th(\"option\", { key: option.value, value: option.value }, option.label),\n\t\t),\n\t);\n}\n\n/** 搜索框(关键字过滤;占满剩余宽度由调用方的 flex 决定)。 */\nexport function SearchInput(props: {\n\tvalue: string;\n\tplaceholder: string;\n\tonChange: (next: string) => void;\n\tariaLabel: string;\n\tsize?: \"sm\" | \"md\" | \"lg\";\n}): ReactNode {\n\tensureUiBase();\n\tconst size = props.size ?? \"md\";\n\treturn h(\"input\", {\n\t\tclassName: `dtl-input dtl-input--${size}`,\n\t\ttype: \"search\",\n\t\t\"aria-label\": props.ariaLabel,\n\t\tplaceholder: props.placeholder,\n\t\tvalue: props.value,\n\t\tspellCheck: false,\n\t\tonChange: (event: ChangeEvent<HTMLInputElement>) => {\n\t\t\tprops.onChange(event.target.value);\n\t\t},\n\t});\n}\n\n/* ── 卡 / chip / 空态 ─────────────────────────────────────────────── */\n\n/** 统计卡:主数字 + 灰色口径小字;点一下联动下方列表筛选。\n * `value` 为 0 时显示「—」(用户 2026-10-17 定稿:0 会被读成「没数据 / 出错了」);\n * `hint` 可以是富文本(如把「停滞」两字标红);\n * `interactive: false` = 纯展示卡(统计台:首页没有已结案可筛,不装可点)。 */\nexport function StatCard(props: {\n\tlabel: string;\n\tvalue: string | number;\n\thint?: ReactNode;\n\tactive?: boolean;\n\tinteractive?: boolean;\n\ttitle?: string;\n\tonClick?: () => void;\n}): ReactNode {\n\tensureUiBase();\n\tconst interactive =\n\t\tprops.interactive !== false && props.onClick !== undefined;\n\tconst shown =\n\t\tprops.value === 0 || props.value === \"0\" ? \"—\" : String(props.value);\n\treturn h(\n\t\tinteractive ? \"button\" : \"div\",\n\t\t{\n\t\t\ttype: interactive ? \"button\" : undefined,\n\t\t\tclassName: `dtl-card dtl-stat${interactive ? \" dtl-card--clickable\" : \"\"}`,\n\t\t\t\"data-active\": props.active === true,\n\t\t\ttitle: props.title,\n\t\t\tonClick: interactive ? props.onClick : undefined,\n\t\t},\n\t\th(\n\t\t\t\"span\",\n\t\t\t{ style: { fontSize: \"var(--dtl-font-sm)\", color: \"var(--dtl-fg-2)\" } },\n\t\t\tprops.label,\n\t\t),\n\t\th(\"span\", { className: \"dtl-stat__value\" }, shown),\n\t\tprops.hint === undefined || props.hint === null || props.hint === \"\"\n\t\t\t? null\n\t\t\t: h(\"span\", { className: \"dtl-stat__hint\" }, props.hint),\n\t);\n}\n\n/** chip(分类 / 标签 / 工作区名)。 */\nexport function Chip(props: { text: string; color?: string }): ReactNode {\n\tensureUiBase();\n\treturn h(\n\t\t\"span\",\n\t\t{\n\t\t\tclassName: \"dtl-chip\",\n\t\t\tstyle:\n\t\t\t\tprops.color === undefined\n\t\t\t\t\t? undefined\n\t\t\t\t\t: { background: props.color, color: \"var(--dtl-on-signal)\" },\n\t\t\ttitle: props.text,\n\t\t},\n\t\tprops.text,\n\t);\n}\n\n/** 标签上限宽度(字符数):1 个中文按 2 计 ⇒ 10 个中文 = 20 个字符(与 CSS 的 20ch 对齐)。 */\nconst TAG_MAX_WIDTH = 20;\n\n/** 显示宽度:全角(中 / 日 / 韩 / 全角符号)一个顶两个英文字符。 */\nfunction displayWidth(text: string): number {\n\tlet width = 0;\n\tfor (const char of text) width += (char.codePointAt(0) ?? 0) > 0x2e80 ? 2 : 1;\n\treturn width;\n}\n\n/**\n * 标签(**唯一**一枚件,用户 2026-10-18):状态 / 执行人 / #标签 都走它,只换 tone。\n * 超过 20 个字符宽 ⇒ 省略号,**且只在被截时**挂悬停提示补出全文(用户 2026-10-19:\n * 不跑马灯;没被截 ⇒ 悬停无反应)。\n */\nexport function Tag(props: {\n\ttext: string;\n\ttone?:\n\t\t| \"neutral\"\n\t\t| \"open\"\n\t\t| \"backlog\"\n\t\t| \"doing\"\n\t\t| \"overdue\"\n\t\t| \"stale\"\n\t\t| \"person\";\n\t/** 悬停提示(**被截时**才显示;默认 = 文本本身)。 */\n\ttitle?: string;\n\t/** 悬停提示(**始终**显示,状态标记的解释走它;优先于 title)。走官方 Tooltip。 */\n\ttip?: string;\n}): ReactNode {\n\tensureUiBase();\n\tconst { text, tone = \"neutral\", title, tip } = props;\n\tconst long = displayWidth(text) > TAG_MAX_WIDTH;\n\tconst label = tip ?? (long ? (title ?? text) : undefined);\n\tconst tag = h(\"span\", { className: `dtl-tag dtl-tag--${tone}` }, text);\n\t// 官方 Tooltip(悬停即出、支持 \\n 多行、portal 逃逸祖先 overflow 裁切)\n\tif (label === undefined) return tag;\n\treturn h(Tooltip, {\n\t\tlabel,\n\t\tside: \"bottom\",\n\t\tportal: true,\n\t\tmaxWidth: 240,\n\t\tchildren: tag,\n\t});\n}\n\n/** 空态:`guide` = 真空引导卡(虚线),`filtered` = 筛选空小字。 */\nexport function EmptyState(props: {\n\ttone: \"guide\" | \"filtered\";\n\ttitle: string;\n\thint?: string;\n}): ReactNode {\n\tensureUiBase();\n\tif (props.tone === \"filtered\")\n\t\treturn h(\"div\", { className: \"dtl-empty-filtered\" }, props.title);\n\treturn h(\n\t\t\"div\",\n\t\t{ className: \"dtl-empty-guide\" },\n\t\th(\n\t\t\t\"div\",\n\t\t\t{\n\t\t\t\tstyle: {\n\t\t\t\t\tfontSize: \"var(--dtl-font-lg)\",\n\t\t\t\t\tfontWeight: 600,\n\t\t\t\t\tmarginBottom: \"var(--dtl-space-1)\",\n\t\t\t\t},\n\t\t\t},\n\t\t\tprops.title,\n\t\t),\n\t\tprops.hint === undefined\n\t\t\t? null\n\t\t\t: h(\n\t\t\t\t\t\"div\",\n\t\t\t\t\t{\n\t\t\t\t\t\tstyle: { fontSize: \"var(--dtl-font-md)\", color: \"var(--dtl-fg-2)\" },\n\t\t\t\t\t},\n\t\t\t\t\tprops.hint,\n\t\t\t\t),\n\t);\n}\n\n/** 台账图标(黑白线条,描边走 currentColor ⇒ 随主题 / 选中态反色)。\n * 侧栏条目与右上浮标共用这一份(图标只画一次,别处不许再画第二个)。 */\nexport function LedgerIcon(props: { size?: number }): ReactNode {\n\tconst size = props.size ?? 18;\n\tconst stroke = {\n\t\tfill: \"none\",\n\t\tstroke: \"currentColor\",\n\t\tstrokeWidth: 7,\n\t\tstrokeLinecap: \"round\",\n\t\tstrokeLinejoin: \"round\",\n\t} as const;\n\treturn h(\n\t\t\"svg\",\n\t\t{ width: size, height: size, viewBox: \"0 0 128 128\", \"aria-hidden\": true },\n\t\th(\"path\", {\n\t\t\td: \"M96 34 A10 10 0 0 1 106 44 V102 A10 10 0 0 1 96 112 H32 A10 10 0 0 1 22 102 V44 A10 10 0 0 1 32 34 Z\",\n\t\t\t...stroke,\n\t\t}),\n\t\th(\"path\", { d: \"M50 22 V46 M78 22 V46\", ...stroke }),\n\t\th(\"path\", { d: \"M44 66 H84 M44 86 H70\", ...stroke }),\n\t);\n}\n\n/* ── 趋势分组柱状图 ───────────────────────────────────────────────────── */\n\n/** 一周三根柱(完成 / 没完成 / 新增)。 */\nexport interface GroupedBarWeek {\n\t/** 轴标签(MM-DD)。 */\n\treadonly label: string;\n\treadonly done: number;\n\treadonly remaining: number;\n\treadonly created: number;\n\t/** 悬停文案。 */\n\treadonly title: string;\n}\n\n/** 千位压缩(1.2k / 12k):y 轴刻度与柱顶数值用,避免 4 位数把刻度挤宽。 */\nfunction compactCount(value: number): string {\n\tif (value >= 10_000) return `${Math.round(value / 1000)}k`;\n\tif (value >= 1000) return `${(value / 1000).toFixed(1)}k`;\n\treturn String(value);\n}\n\n/** 分组柱状图(div 柱,无新依赖):完成(蓝)/ 没完成(琥珀)/ 新增(灰)各一细柱。\n * - 高度全用百分比 ⇒ 绘图区随卡片拉伸,图表卡与左边 8 块**完全等高**;\n * - y 轴三档刻度 + 淡网格线;柱顶只标「完成」(3 系列 × 8 周数值会糊成一片);\n * - hover 整列提亮 + 浮卡(日期 + 三个数)——原生 title 太慢;\n * - **没有**均值线与长注释(用户 2026-10-17:均值不要、注释太长不要)。 */\nexport function GroupedBarChart(props: {\n\tweeks: readonly GroupedBarWeek[];\n\tariaLabel: string;\n\tdoneLabel: string;\n\tremainingLabel: string;\n\tcreatedLabel: string;\n}): ReactNode {\n\tensureUiBase();\n\tconst [hover, setHover] = useState<number | null>(null);\n\tconst top = Math.max(\n\t\t1,\n\t\tprops.weeks.reduce(\n\t\t\t(peak, week) => Math.max(peak, week.done, week.remaining, week.created),\n\t\t\t0,\n\t\t),\n\t);\n\tconst ticks = [0, top / 2, top];\n\tconst pct = (value: number): string => `${(value / top) * 100}%`;\n\tconst columnStyle = (index: number): Record<string, string | number> => ({\n\t\tleft: `${(index / props.weeks.length) * 100}%`,\n\t\tright: `${((props.weeks.length - index - 1) / props.weeks.length) * 100}%`,\n\t});\n\t// 浮卡定位:贴边两列向内收,其余居中(否则溢出图表卡)\n\tconst tipStyle = (index: number): Record<string, string | number> => {\n\t\tif (index <= 1) return { left: 0 };\n\t\tif (index >= props.weeks.length - 2) return { right: 0 };\n\t\treturn {\n\t\t\tleft: `${((index + 0.5) / props.weeks.length) * 100}%`,\n\t\t\ttransform: \"translateX(-50%)\",\n\t\t};\n\t};\n\treturn h(\n\t\t\"div\",\n\t\t{ className: \"dtl-gchart-wrap\" },\n\t\th(\n\t\t\t\"div\",\n\t\t\t{\n\t\t\t\tclassName: \"dtl-gchart\",\n\t\t\t\trole: \"img\",\n\t\t\t\t\"aria-label\": props.ariaLabel,\n\t\t\t\tonMouseLeave: () => {\n\t\t\t\t\tsetHover(null);\n\t\t\t\t},\n\t\t\t},\n\t\t\tticks.map((tick) =>\n\t\t\t\th(\"div\", {\n\t\t\t\t\tkey: `grid-${String(tick)}`,\n\t\t\t\t\tclassName: \"dtl-gchart__grid\",\n\t\t\t\t\tstyle: { bottom: pct(tick) },\n\t\t\t\t}),\n\t\t\t),\n\t\t\tticks.map((tick) =>\n\t\t\t\th(\n\t\t\t\t\t\"span\",\n\t\t\t\t\t{\n\t\t\t\t\t\tkey: `tick-${String(tick)}`,\n\t\t\t\t\t\tclassName: \"dtl-gchart__ytick\",\n\t\t\t\t\t\tstyle: { bottom: pct(tick) },\n\t\t\t\t\t},\n\t\t\t\t\tcompactCount(Math.round(tick)),\n\t\t\t\t),\n\t\t\t),\n\t\t\tprops.weeks.map((week, index) =>\n\t\t\t\th(\n\t\t\t\t\t\"div\",\n\t\t\t\t\t{\n\t\t\t\t\t\tkey: week.label,\n\t\t\t\t\t\tclassName: \"dtl-gchart__col\",\n\t\t\t\t\t\tstyle: columnStyle(index),\n\t\t\t\t\t\tonMouseEnter: () => {\n\t\t\t\t\t\t\tsetHover(index);\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\th(\n\t\t\t\t\t\t\"div\",\n\t\t\t\t\t\t{ className: \"dtl-gchart__pair\" },\n\t\t\t\t\t\th(\"span\", {\n\t\t\t\t\t\t\tclassName: \"dtl-gchart__bar dtl-gchart__bar--done\",\n\t\t\t\t\t\t\tstyle: {\n\t\t\t\t\t\t\t\theight: pct(week.done),\n\t\t\t\t\t\t\t\tminHeight: week.done > 0 ? \"2px\" : undefined,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t}),\n\t\t\t\t\t\th(\"span\", {\n\t\t\t\t\t\t\tclassName: \"dtl-gchart__bar dtl-gchart__bar--remaining\",\n\t\t\t\t\t\t\tstyle: {\n\t\t\t\t\t\t\t\theight: pct(week.remaining),\n\t\t\t\t\t\t\t\tminHeight: week.remaining > 0 ? \"2px\" : undefined,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t}),\n\t\t\t\t\t\th(\"span\", {\n\t\t\t\t\t\t\tclassName: \"dtl-gchart__bar dtl-gchart__bar--created\",\n\t\t\t\t\t\t\tstyle: {\n\t\t\t\t\t\t\t\theight: pct(week.created),\n\t\t\t\t\t\t\t\tminHeight: week.created > 0 ? \"2px\" : undefined,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t}),\n\t\t\t\t\t),\n\t\t\t\t\tweek.done === 0\n\t\t\t\t\t\t? null\n\t\t\t\t\t\t: h(\n\t\t\t\t\t\t\t\t\"span\",\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tclassName: \"dtl-gchart__val\",\n\t\t\t\t\t\t\t\t\tstyle: { bottom: `calc(${pct(week.done)} + 3px)` },\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\tString(week.done),\n\t\t\t\t\t\t\t),\n\t\t\t\t\th(\"span\", { className: \"dtl-gchart__label\" }, week.label),\n\t\t\t\t),\n\t\t\t),\n\t\t\thover === null\n\t\t\t\t? null\n\t\t\t\t: h(\n\t\t\t\t\t\t\"div\",\n\t\t\t\t\t\t{ className: \"dtl-gchart__tip\", style: tipStyle(hover) },\n\t\t\t\t\t\th(\"b\", null, props.weeks[hover].title),\n\t\t\t\t\t\th(\n\t\t\t\t\t\t\t\"div\",\n\t\t\t\t\t\t\tnull,\n\t\t\t\t\t\t\th(\"i\", { style: { background: \"var(--dtl-business)\" } }),\n\t\t\t\t\t\t\t`${props.doneLabel} ${props.weeks[hover].done}`,\n\t\t\t\t\t\t),\n\t\t\t\t\t\th(\n\t\t\t\t\t\t\t\"div\",\n\t\t\t\t\t\t\tnull,\n\t\t\t\t\t\t\th(\"i\", { style: { background: \"var(--dtl-chart-remaining)\" } }),\n\t\t\t\t\t\t\t`${props.remainingLabel} ${props.weeks[hover].remaining}`,\n\t\t\t\t\t\t),\n\t\t\t\t\t\th(\n\t\t\t\t\t\t\t\"div\",\n\t\t\t\t\t\t\tnull,\n\t\t\t\t\t\t\th(\"i\", { style: { background: \"var(--dtl-chart-created)\" } }),\n\t\t\t\t\t\t\t`${props.createdLabel} ${props.weeks[hover].created}`,\n\t\t\t\t\t\t),\n\t\t\t\t\t),\n\t\t),\n\t);\n}\n\n/** 图例(完成 / 没完成 / 新增 三个色块)。 */\nexport function ChartLegend(props: {\n\tdoneLabel: string;\n\tremainingLabel: string;\n\tcreatedLabel: string;\n}): ReactNode {\n\tensureUiBase();\n\treturn h(\n\t\t\"div\",\n\t\t{ className: \"dtl-gchart-legend\" },\n\t\th(\n\t\t\t\"span\",\n\t\t\tnull,\n\t\t\th(\"i\", { style: { background: \"var(--dtl-business)\" } }),\n\t\t\tprops.doneLabel,\n\t\t),\n\t\th(\n\t\t\t\"span\",\n\t\t\tnull,\n\t\t\th(\"i\", { style: { background: \"var(--dtl-chart-remaining)\" } }),\n\t\t\tprops.remainingLabel,\n\t\t),\n\t\th(\n\t\t\t\"span\",\n\t\t\tnull,\n\t\t\th(\"i\", { style: { background: \"var(--dtl-chart-created)\" } }),\n\t\t\tprops.createdLabel,\n\t\t),\n\t);\n}\n","/**\n * 任务行(宿主**无表格件** ⇒ 自绘),**两种形态**(用户 2026-10-17 定稿:两区视觉必须不同,\n * 且**互不重用**):\n *\n * A. `mine`(我的待办)= 整行一张卡,样式照抄 dispatch-table 任务配置卡:\n * 左缘 6×36 状态条 + 标题行 + 第二行工作区/标签;右侧灰字时长;悬停出\n * 「继续 / 结束 / 释放」;最右常驻「查看」放大镜钮。\n *\n * B. `others`(全部待办)= 连体长表里的一行(用户 2026-10-18 定稿):**无卡片、无外框**,\n * 行 = 一条淡分隔线格:上下居中的状态圆点 + 任务(标题行 + 标签行;**标签行最前是状态标签**)\n * + **执行人列**(原状态位,有执行人才摆 `@名字` 标签)+ 最右「@创建人 创建于 年-月-日 时:分:秒」\n * (悬停掉时分秒并让位给操作钮)+ 查看。\n * 状态一律**标签型、五色**(用户 2026-10-18:原来是一排素字 / pill,现在与人员**位置互换**):\n * 灰=待认领 / 蓝=进行中 / 黄=积压 / 橙=逾期 / 红=停滞;三个异常标签悬停给**配置出来的**\n * 阈值解释(staleDays / overdueDays / backlogDays 由 host 下发)。圆点颜色同色系。\n *\n * 按钮(含查看)**不各判各的**:权限一律问 `resolveActions()`(rows.ts),本文件只按返回值画。\n *\n * 按钮点击行为(含查看)归「任务按钮与会话交接」任务,本文件只做样子与提示。\n */\n\nimport {\n\tIconCheckOutlineRegular,\n\tIconChevronRightOutlineRegular,\n\tIconDownloadOutlineRegular,\n\tIconSearchOutlineRegular,\n\tTooltip,\n} from \"@deepseek-ai/dsh-client-ui-primitives\";\nimport { createElement as h, type ReactNode } from \"react\";\nimport { formatDateTime } from \"./format\";\nimport type { Translate } from \"./locales\";\nimport { CLOSED_ACTIONS, displayName, type Row, resolveActions } from \"./rows\";\nimport type { BoardPayload } from \"./types\";\nimport { Tag } from \"./ui\";\n\ntype Tone = \"doing\" | \"overdue\" | \"stale\" | \"backlog\" | \"open\" | \"closed\";\n\n/** 行标题:在办 = 任务名(缺则任务号);已结案 = 任务包名(缺则「完成了什么」首句)。 */\nfunction titleOf(row: Row): string {\n\tif (row.kind === \"task\") return row.task.title || row.task.id;\n\t// 空串也算「没有」:用 || 而不是 ??,否则空标题会顶掉摘要\n\tconst title = row.record.workpackage || row.record.summary || \"\";\n\treturn title !== \"\" ? title : (row.record.src ?? \"—\");\n}\n\n/** 状态语义(异常优先:停滞 > 逾期 > 积压;三者都是 host 按时间算出来的,不是状态)。\n * 只决定圆点 / 左缘色条这类**单色位**——标签可以多枚,见 MARKS。 */\nfunction toneOf(row: Row): Tone {\n\tif (row.kind !== \"task\") return \"closed\";\n\tif (row.task.stale === true) return \"stale\";\n\tif (row.task.overdue === true) return \"overdue\";\n\tif (row.task.backlog === true) return \"backlog\";\n\tif (row.task.status === \"open\") return \"open\";\n\treturn \"doing\";\n}\n\n/** 三个异常标记**可叠加**(用户 2026-10-19):一条任务能同时逾期 + 停滞,两枚标签都要摆。\n * 积压与逾期 / 停滞不会共存(前者是待认领,后两者是进行中),故最多 2 枚。 */\nconst MARKS = [\"backlog\", \"overdue\", \"stale\"] as const;\n\n/** 状态文案(已结案没有在办状态 ⇒ 不给标签)。 */\nfunction statusLabel(tone: Tone, t: Translate): string | null {\n\tif (tone === \"stale\") return t(\"statusStale\");\n\tif (tone === \"overdue\") return t(\"statusOverdue\");\n\tif (tone === \"backlog\") return t(\"statusBacklog\");\n\tif (tone === \"open\") return t(\"statusOpen\");\n\tif (tone === \"doing\") return t(\"statusActive\");\n\treturn null;\n}\n\nexport function TaskRowView(props: {\n\tt: Translate;\n\trow: Row;\n\t/** 形态:我的待办(卡片)/ 全部待办(表格行)——两区视觉必须不同、互不重用。 */\n\tvariant: \"mine\" | \"others\";\n\t/** 快照:问动作权限(是不是我的 / 能不能认领),并取 host 下发的三个阈值做悬停解释。 */\n\tboard: BoardPayload | null;\n}): ReactNode {\n\tconst { t, row, variant, board } = props;\n\tconst tone = toneOf(row);\n\tconst isTask = row.kind === \"task\";\n\tconst tags = (row.kind === \"task\" ? row.task.tags : row.record.tags) ?? [];\n\n\t// 创建日期(第一行灰徽只给日期)。\n\tconst created =\n\t\trow.kind === \"task\"\n\t\t\t? (row.task.created ?? null)\n\t\t\t: (row.record.created ?? null);\n\tconst createdDay =\n\t\tcreated !== null && created !== undefined && Date.parse(created) >= 0\n\t\t\t? formatDateTime(created).slice(0, 10)\n\t\t\t: null;\n\n\t// 标签悬停解释(用户 2026-10-19):一律「谁 / 何时开始 / 最后更新 / 多少天」,天数由 host 下发,\n\t// 前端不自行推算;缺时间就报「时间未知」,不编。\n\tconst stamp = (value: string | null | undefined): string =>\n\t\tvalue === null || value === undefined\n\t\t\t? t(\"timeUnknown\")\n\t\t\t: formatDateTime(value, { seconds: true, fallback: t(\"timeUnknown\") });\n\tconst dayText = (n: number | null | undefined): string =>\n\t\tn === null || n === undefined ? t(\"daysNone\") : t(\"daysValue\", { n });\n\tconst detailTip = (which: Exclude<Tone, \"closed\">): string | undefined => {\n\t\tif (row.kind !== \"task\") return undefined;\n\t\tconst { task } = row;\n\t\tconst owner = displayName(task.owner_name, task.owner);\n\t\tconst who = owner === \"\" ? t(\"ownerUnclaimed\") : `@${owner}`;\n\t\tconst started = stamp(task.started ?? task.created);\n\t\tconst updated = stamp(task.updated ?? task.started ?? task.created);\n\t\tif (which === \"open\") return t(\"tipOpen\", { created: stamp(task.created) });\n\t\tif (which === \"backlog\")\n\t\t\treturn t(\"tipBacklog\", {\n\t\t\t\tcreated: stamp(task.created),\n\t\t\t\td: dayText(task.waitingDays),\n\t\t\t});\n\t\tif (which === \"doing\") return t(\"tipDoing\", { who, started, updated });\n\t\tif (which === \"overdue\")\n\t\t\treturn t(\"tipOverdue\", {\n\t\t\t\twho,\n\t\t\t\tstarted,\n\t\t\t\tupdated,\n\t\t\t\td: dayText(task.ageDays),\n\t\t\t});\n\t\treturn t(\"tipStale\", { who, started, updated, d: dayText(task.idleDays) });\n\t};\n\t// 动作权限:**唯一**判定(用户 2026-10-18)——两区同一套,不许各判各的;本文件只按返回值画。\n\tconst actions = isTask ? resolveActions(row.task, board) : CLOSED_ACTIONS;\n\n\t// 动作钮:四个 + 查看,各一份(两区共用,不许各画一套)。\n\t// 悬停说明统一走官方 Tooltip(portal 逃逸裁切、hover 即出),不在 CSS 里手搓 ::after 浮层。\n\t// 「查看」:两区都有、统一最右、放大镜图标(用户 2026-10-17)。\n\tconst viewButton = h(Tooltip, {\n\t\tlabel: t(\"viewDetail\"),\n\t\tside: \"bottom\",\n\t\tportal: true,\n\t\tmaxWidth: 240,\n\t\tchildren: h(\n\t\t\t\"button\",\n\t\t\t{ type: \"button\", className: \"dtl-viewbtn\" },\n\t\t\th(IconSearchOutlineRegular, { size: 14 }),\n\t\t),\n\t});\n\tconst tipBtn = (\n\t\ticon: ReactNode,\n\t\tactionKey:\n\t\t\t| \"actionClaim\"\n\t\t\t| \"actionResume\"\n\t\t\t| \"actionFinish\"\n\t\t\t| \"actionRelease\",\n\t\ttipKey: \"tipClaim\" | \"tipResume\" | \"tipFinish\" | \"tipRelease\",\n\t): ReactNode =>\n\t\th(Tooltip, {\n\t\t\tlabel: t(tipKey),\n\t\t\tside: \"bottom\",\n\t\t\tportal: true,\n\t\t\tmaxWidth: 240,\n\t\t\tchildren: h(\n\t\t\t\t\"button\",\n\t\t\t\t{ type: \"button\", className: \"dtl-minibtn\" },\n\t\t\t\t...(icon ? [icon, t(actionKey)] : [t(actionKey)]),\n\t\t\t),\n\t\t});\n\tconst claimButton = tipBtn(\n\t\th(IconDownloadOutlineRegular, { size: 14 }),\n\t\t\"actionClaim\",\n\t\t\"tipClaim\",\n\t);\n\tconst resumeButton = tipBtn(\n\t\th(IconChevronRightOutlineRegular, { size: 14 }),\n\t\t\"actionResume\",\n\t\t\"tipResume\",\n\t);\n\tconst finishButton = tipBtn(\n\t\th(IconCheckOutlineRegular, { size: 14 }),\n\t\t\"actionFinish\",\n\t\t\"tipFinish\",\n\t);\n\t// 释放:官方 rc.2 无断链图标(已全量核实)⇒ 纯文字,不用叉\n\tconst releaseButton = tipBtn(null, \"actionRelease\", \"tipRelease\");\n\n\t// 状态标签(五色实心块,用户 2026-10-18 定稿):已结案没有在办状态 ⇒ 不摆;\n\t// 三枚异常标签带 host 配置的阈值解释(没配就不解释,不编)。\n\tconst tagOf = (which: Exclude<Tone, \"closed\">, tip?: string): ReactNode => {\n\t\tconst text = statusLabel(which, t) ?? \"\";\n\t\treturn h(Tag, {\n\t\t\tkey: which,\n\t\t\ttext,\n\t\t\ttone: which,\n\t\t\ttip: tip ?? detailTip(which),\n\t\t});\n\t};\n\tconst markTones = isTask\n\t\t? MARKS.filter((which) => row.task[which] === true)\n\t\t: [];\n\t// 异常标记全部摆出来;一个都没有 ⇒ 退回归属状态(待认领 / 进行中)那一枚\n\tconst statusTags =\n\t\ttone === \"closed\"\n\t\t\t? []\n\t\t\t: (markTones.length > 0\n\t\t\t\t\t? markTones\n\t\t\t\t\t: [tone as Exclude<Tone, \"closed\">]\n\t\t\t\t).map((which) => tagOf(which));\n\t// 「我的待办」卡只摆异常标记(进行中只靠左缘色条,不再重复一枚)\n\tconst alarmTags = markTones.map((which) => tagOf(which));\n\n\t// 第一行(「我的待办」卡):标题 + 创建徽 + 异常标签\n\tconst titleLine = h(\n\t\t\"div\",\n\t\t{ className: \"dtl-taskrow__l1\" },\n\t\th(\n\t\t\t\"span\",\n\t\t\t{ className: \"dtl-taskrow__title dtl-ellipsis\", title: titleOf(row) },\n\t\t\ttitleOf(row),\n\t\t),\n\t\tcreatedDay === null\n\t\t\t? null\n\t\t\t: h(\n\t\t\t\t\t\"span\",\n\t\t\t\t\t{ className: \"dtl-taskrow__stamp\" },\n\t\t\t\t\t`[${t(\"fieldCreatedStamp\", { day: createdDay })}]`,\n\t\t\t\t),\n\t\t...alarmTags,\n\t);\n\n\t// 第一行(表格行):独立类族,不沾卡片基类(用户 2026-10-18)。\n\t// 只有标题 —— 创建信息挪到最右、状态进标签行,标题行不再重复一遍。\n\tconst orowTitleLine = h(\n\t\t\"div\",\n\t\t{ className: \"dtl-orow__title\" },\n\t\th(\n\t\t\t\"span\",\n\t\t\t{ className: \"dtl-orow__name dtl-ellipsis\", title: titleOf(row) },\n\t\t\ttitleOf(row),\n\t\t),\n\t);\n\n\t// ── 形态 B:全部待办 = 真表格行(无卡片、无外框,一行一格)──\n\tif (variant === \"others\") {\n\t\t// 已结案行没有「执行人」列 ⇒ 那格摆**创建人**(owner 会被交接改走,不是“创建于”的人)\n\t\tconst creator = isTask ? row.task.creator : row.record.creator;\n\t\tconst owner = isTask ? row.task.owner : null;\n\t\tconst creatorLabel = displayName(\n\t\t\tisTask ? row.task.creator_name : row.record.creator_name,\n\t\t\tcreator,\n\t\t);\n\t\tconst hasOwner = !(owner === null || owner === undefined || owner === \"\");\n\t\tconst who = creatorLabel === \"\" ? \"—\" : `@${creatorLabel}`;\n\t\tconst createdOk =\n\t\t\tcreated !== null && created !== undefined && Date.parse(created) >= 0;\n\t\t// 执行人的悬停提示(**只在名字被截断时才显示**,见 Tag):全名 + **什么时候开始执行**\n\t\t// (任务上的 started;没有就报「时间未知」,不编)\n\t\tconst startedOk =\n\t\t\tisTask &&\n\t\t\trow.task.started !== null &&\n\t\t\trow.task.started !== undefined &&\n\t\t\tDate.parse(row.task.started) >= 0;\n\t\tconst ownerTip = t(\"startedAt\", {\n\t\t\twho: displayName(isTask ? row.task.owner_name : null, owner),\n\t\t\twhen: startedOk\n\t\t\t\t? formatDateTime(String(row.task.started))\n\t\t\t\t: t(\"timeUnknown\"),\n\t\t});\n\t\t// 标签行:**状态在最前**(原执行人位),#标签跟在后面(用户 2026-10-18 位置互换)\n\t\tconst tagLine = h(\n\t\t\t\"div\",\n\t\t\t{ className: \"dtl-orow__tags\" },\n\t\t\t...statusTags,\n\t\t\ttags.map((tag) => h(Tag, { key: tag, text: `#${tag}` })),\n\t\t);\n\t\treturn h(\n\t\t\t\"div\",\n\t\t\t{ className: \"dtl-orow\" },\n\t\t\th(\n\t\t\t\t\"div\",\n\t\t\t\t{ className: \"dtl-orow__row\" },\n\t\t\t\t// 行标识:上下居中圆点(段头是文件夹/竖线,两处刻意不同)\n\t\t\t\th(\"span\", { className: `dtl-dot dtl-dot--${tone}` }),\n\t\t\t\th(\n\t\t\t\t\t\"div\",\n\t\t\t\t\t{ className: \"dtl-tcell dtl-tcell--title\" },\n\t\t\t\t\torowTitleLine,\n\t\t\t\t\ttagLine,\n\t\t\t\t),\n\t\t\t\t// 执行人列(原状态位):有执行人 ⇒ 一枚 @名字 标签,悬停给「谁 什么时候开始执行」\n\t\t\t\t// (页面不许跳:右侧槽位宽度是常驻的,hover 只换可见性 ⇒ 这个提示不会跟着飘)\n\t\t\t\th(\n\t\t\t\t\t\"span\",\n\t\t\t\t\t{ className: \"dtl-tcell dtl-tcell--status\" },\n\t\t\t\t\t// 名字上限 20 字(Tag 的 20ch);超了 ⇒ 省略号 + 悬停补全名(ownerTip)\n\t\t\t\t\thasOwner\n\t\t\t\t\t\t? h(Tag, {\n\t\t\t\t\t\t\t\t// owner 是 uuid:显示名优先,旧数据没有才退回 uuid\n\t\t\t\t\t\t\t\ttext: `@${displayName(isTask ? row.task.owner_name : null, owner)}`,\n\t\t\t\t\t\t\t\ttone: \"person\",\n\t\t\t\t\t\t\t\ttitle: ownerTip,\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t: null,\n\t\t\t\t),\n\t\t\t\t// 最右**一个槽**:创建信息 ⇄ 操作钮二选一(用户 2026-10-18:悬停就把创建信息整条干掉,\n\t\t\t\t// 按钮顶上那一格;两个都常驻布局 ⇒ 行宽不变、页面不跳)\n\t\t\t\th(\n\t\t\t\t\t\"span\",\n\t\t\t\t\t{ className: \"dtl-orow__slot\" },\n\t\t\t\t\th(\n\t\t\t\t\t\t\"span\",\n\t\t\t\t\t\t{ className: \"dtl-orow__created\" },\n\t\t\t\t\t\tt(\"createdAt\", {\n\t\t\t\t\t\t\twho,\n\t\t\t\t\t\t\twhen: createdOk\n\t\t\t\t\t\t\t\t? formatDateTime(String(created))\n\t\t\t\t\t\t\t\t: t(\"timeUnknown\"),\n\t\t\t\t\t\t}),\n\t\t\t\t\t),\n\t\t\t\t\t// 动作排:**同一排、同一间距**(用户 2026-10-18:查看钮不许单独一档间距);\n\t\t\t\t\t// 谁出来由 resolveActions 说了算 —— 我的 ⇒ 继续/结束/释放,待认领 ⇒ 认领\n\t\t\t\t\th(\n\t\t\t\t\t\t\"span\",\n\t\t\t\t\t\t{ className: \"dtl-orow__actions\" },\n\t\t\t\t\t\tactions.claim ? claimButton : null,\n\t\t\t\t\t\tactions.resume ? resumeButton : null,\n\t\t\t\t\t\tactions.finish ? finishButton : null,\n\t\t\t\t\t\tactions.release ? releaseButton : null,\n\t\t\t\t\t\tactions.view ? viewButton : null,\n\t\t\t\t\t),\n\t\t\t\t),\n\t\t\t),\n\t\t);\n\t}\n\n\t// ── 形态 A:我的待办 = 卡片(dispatch 任务配置卡同款)──\n\tconst parts: string[] = [];\n\tif (isTask) {\n\t\tconst startRaw = row.task.started ?? row.task.created;\n\t\tif (\n\t\t\tstartRaw !== undefined &&\n\t\t\tstartRaw !== null &&\n\t\t\tstartRaw !== \"\" &&\n\t\t\tDate.parse(startRaw) >= 0\n\t\t) {\n\t\t\tparts.push(\n\t\t\t\t`${formatDateTime(startRaw).slice(0, 10)} ${t(\"fieldStarted\")}`,\n\t\t\t);\n\t\t}\n\t\tif (row.task.ageDays !== null && row.task.ageDays !== undefined) {\n\t\t\tparts.push(\n\t\t\t\trow.task.ageDays === 0\n\t\t\t\t\t? t(\"ageToday\")\n\t\t\t\t\t: t(\"ageDaysText\", { n: row.task.ageDays }),\n\t\t\t);\n\t\t}\n\t} else {\n\t\tparts.push(\n\t\t\t`${t(\"fieldFinished\")} ${formatDateTime(row.record.time || row.record.created || \"\", { fallback: t(\"timeUnknown\") })}`,\n\t\t);\n\t}\n\treturn h(\n\t\t\"div\",\n\t\t{ className: \"dtl-taskrow\" },\n\t\th(\n\t\t\t\"div\",\n\t\t\t{ className: \"dtl-taskrow__row\" },\n\t\t\th(\"span\", { className: `dtl-rail dtl-rail--${tone}` }),\n\t\t\th(\n\t\t\t\t\"div\",\n\t\t\t\t{ style: { flex: \"1 1 auto\", minWidth: 0 } },\n\t\t\t\ttitleLine,\n\t\t\t\th(\n\t\t\t\t\t\"div\",\n\t\t\t\t\t{ className: \"dtl-taskrow__l2\" },\n\t\t\t\t\th(\n\t\t\t\t\t\t\"span\",\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tclassName: \"dtl-wstag dtl-ellipsis\",\n\t\t\t\t\t\t\ttitle: row.kind === \"task\" ? row.task.workspace.title : \"\",\n\t\t\t\t\t\t},\n\t\t\t\t\t\trow.kind === \"task\" ? row.task.workspace.title : \"\",\n\t\t\t\t\t),\n\t\t\t\t\ttags.map((tag) => h(Tag, { key: tag, text: `#${tag}` })),\n\t\t\t\t),\n\t\t\t),\n\t\t\th(\n\t\t\t\t\"span\",\n\t\t\t\t{ className: \"dtl-taskrow__when\" },\n\t\t\t\tparts.length === 0 ? t(\"timeUnknown\") : parts.join(\"丨\"),\n\t\t\t),\n\t\t\t// 动作排:继续 / 结束 / 释放 + 查看 —— **同一排、同一间距**\n\t\t\t// (用户 2026-10-18:查看钮原来是独立的一格,离前面的按钮远一档)\n\t\t\t// 谁出来由 resolveActions 说了算(与下面「全部待办」**同一个方法**,不再各判各的)\n\t\t\th(\n\t\t\t\t\"span\",\n\t\t\t\t{ className: \"dtl-taskrow__actions\" },\n\t\t\t\tactions.resume ? resumeButton : null,\n\t\t\t\tactions.finish ? finishButton : null,\n\t\t\t\tactions.release ? releaseButton : null,\n\t\t\t\tactions.view ? viewButton : null,\n\t\t\t),\n\t\t),\n\t);\n}\n","/**\n * 看板首页(`main` 槽整页内容):8 统计卡 + 近 8 周趋势图 + 两区任务列表。\n * 定稿见 docs/design/features/board-home.md §二(2026-10-17 专家组改版);\n * 按钮矩阵归「任务按钮与会话交接」任务(写入路径 A/B 未拍板),本页**不画**任务动作按钮。\n *\n * 刷新纪律(2026-10-17 拍板):挂载首读 + 手动刷新按钮,**不轮询**;空态三分\n * (未就绪不渲染 / 真空引导卡 / 筛选空小字)。\n */\n\nimport {\n\tIconChecklistOutlineRegular,\n\tIconFlatListOutlineRegular,\n\tIconFolderCloseRegular,\n\tIconFolderOpenRegular,\n\tIconRefreshOutlineRegular,\n} from \"@deepseek-ai/dsh-client-ui-primitives\";\nimport {\n\ttype ChangeEvent,\n\tcreateElement as h,\n\ttype ReactNode,\n\tuseEffect,\n\tuseMemo,\n\tuseState,\n\tuseSyncExternalStore,\n} from \"react\";\nimport type { LocaleKey, Translate } from \"./locales\";\nimport { isMine, selectView, type WorkspaceGroup } from \"./rows\";\nimport {\n\tboardSnapshot,\n\tboardSubscribe,\n\trefresh,\n\ttype StatusFilter,\n\tsetQuery,\n} from \"./store\";\nimport { TaskRowView } from \"./task-row\";\nimport type { BoardPayload, PeriodCounts } from \"./types\";\nimport {\n\tButton,\n\tChartLegend,\n\tEmptyState,\n\tensureUiBase,\n\tGroupedBarChart,\n\tSearchInput,\n\tSegmented,\n\tSelect,\n\tStatCard,\n} from \"./ui\";\n\ntype Tab = \"tasks\" | \"stats\";\n\n/** 整页容器:占满中栏、自己滚动。 */\nconst pageStyle: Record<string, string | number> = {\n\theight: \"100%\",\n\twidth: \"100%\",\n\tboxSizing: \"border-box\",\n\toverflow: \"auto\",\n\tpadding: \"24px 22px\",\n\tcolor: \"var(--dtl-fg)\",\n};\nconst headerStyle: Record<string, string | number> = {\n\tdisplay: \"flex\",\n\talignItems: \"center\",\n\tjustifyContent: \"space-between\",\n\tgap: \"var(--dtl-space-3)\",\n\tflexWrap: \"wrap\",\n\tmarginBottom: \"var(--dtl-space-4)\",\n};\nconst titleStyle: Record<string, string | number> = {\n\tfontSize: \"var(--dtl-font-xl)\",\n\tfontWeight: 600,\n};\n/** 统计区:左 8 块(2 行 × 4 列)+ 右趋势图,参考图同款分栏。\n * 列数写死 4 → 2(媒体查询在 ui.ts 的 .dtl-stats / .dtl-stats__cards 里),\n * 绝不给 3 列——3 列会排出 3+1 的非对称(用户 2026-10-17:必须上下对称)。 */\nconst statsRowStyle: Record<string, string | number> = {\n\tmarginBottom: \"var(--dtl-space-4)\",\n};\nconst chartCardStyle: Record<string, string | number> = {\n\tdisplay: \"flex\",\n\tflexDirection: \"column\",\n\tgap: \"var(--dtl-space-2)\",\n\tpadding: \"var(--dtl-space-2) var(--dtl-space-3)\",\n};\nconst hintStyle: Record<string, string | number> = {\n\tfontSize: \"var(--dtl-font-sm)\",\n\tcolor: \"var(--dtl-fg-2)\",\n};\n/** 分区标题行:垂直居中(用户 2026-10-17:图标 / 标题 / 计数不许像下楼梯一样逐个低);\n * 上下留白**翻倍**(用户 2026-10-18:两个大标题太挤)。 */\nconst regionHeadRowStyle: Record<string, string | number> = {\n\tdisplay: \"flex\",\n\talignItems: \"center\",\n\tgap: \"var(--dtl-space-2)\",\n\tmargin: \"calc(var(--dtl-space-4) * 2) 0 calc(var(--dtl-space-2) * 2)\",\n};\nconst regionHeadTitleStyle: Record<string, string | number> = {\n\tfontSize: \"var(--dtl-font-lg)\",\n\tfontWeight: 600,\n};\n/** 工作区下拉最小宽度(用户 2026-10-17:内容自适应,下限 = 旧定宽 175 的 3/4 ≈ 131)。 */\nconst WORKSPACE_SELECT_MIN = 131;\n/** 搜索框宽度(用户 2026-10-17:两区同款,96×2 = 192)。 */\nconst SEARCH_WIDTH = 192;\n\n/** 分组默认折叠阈值(组内太多条时先收起,用户点开)。 */\nconst GROUP_COLLAPSE_OVER = 30;\n\nexport function BoardHome(props: {\n\tt: Translate;\n\tonBack: () => void;\n}): ReactNode {\n\tconst { t, onBack } = props;\n\tensureUiBase();\n\tconst state = useSyncExternalStore(boardSubscribe, boardSnapshot);\n\tconst [tab, setTab] = useState<Tab>(\"tasks\");\n\n\t// 打开面板首读(后端纯按需,无推送无轮询)。\n\tuseEffect(() => {\n\t\tvoid refresh();\n\t}, []);\n\n\tconst board = state.board;\n\tconst view = useMemo(() => selectView(state), [state]);\n\tconst stats = board?.stats;\n\t// 趋势走慢路径(`/board/trend`,读 history):晚到不影响列表;未到 / 失败时由统计卡与图表区各自兜底。\n\tconst trend = state.trend;\n\tconst periods = trend?.trend;\n\tconst trendPending =\n\t\tstate.trendStatus === \"idle\" || state.trendStatus === \"loading\";\n\t/** 快照 + 趋势两段各自的降级工作区(op 不同,合并展示,别装没看见)。 */\n\tconst degraded = [...(board?.degraded ?? []), ...(trend?.degraded ?? [])];\n\t// 工作区下拉候选(用户 2026-10-17):不读系统全量工作区,只从「我的」任务里提取工作区并排重\n\t// ⇒ 没有我任务的工作区不出现;口径与第一区一致(isMine 同源)。\n\tconst workspaceOptions = useMemo(\n\t\t() => [\n\t\t\t{ value: \"\", label: t(\"workspaceAll\") },\n\t\t\t...[\n\t\t\t\t...new Map(\n\t\t\t\t\t(board?.tasks ?? [])\n\t\t\t\t\t\t.filter((task) => isMine(task, board))\n\t\t\t\t\t\t.map((task) => [task.workspace.id, task.workspace.title]),\n\t\t\t\t),\n\t\t\t].map(([id, title]) => ({ value: id, label: title })),\n\t\t],\n\t\t[board, t],\n\t);\n\t/** 统计卡:纯展示(用户 2026-10-17:先全去掉点击,界面定稿后再议滚动 / 筛选联动)。 */\n\tconst card = (\n\t\tlabel: LocaleKey,\n\t\tvalue: number,\n\t\thint: string,\n\t\ttitle?: string,\n\t): ReactNode =>\n\t\th(StatCard, {\n\t\t\tlabel: t(label),\n\t\t\tvalue,\n\t\t\thint,\n\t\t\ttitle,\n\t\t\tinteractive: false,\n\t\t});\n\n\t/** 子集卡占比小字:分母为 0 或自己没有 ⇒ 不显示(不拿 0% 充数)。 */\n\tconst share = (part: number, whole: number, key: LocaleKey): string =>\n\t\tpart > 0 && whole > 0\n\t\t\t? t(key, { n: Math.round((part / whole) * 100) })\n\t\t\t: \"\";\n\n\t/** 统计台卡:不可点(首页没有已结案可筛),hover 给具体日期区间。\n\t * 趋势未到 / 读挂 ⇒ 数字留 '—'(StatCard 对 0 的处理)、小字整条不显示,**不拿 0 充数**。 */\n\tconst periodCard = (\n\t\tlabel: LocaleKey,\n\t\tperiod: PeriodCounts | undefined,\n\t): ReactNode =>\n\t\th(StatCard, {\n\t\t\tlabel: t(label),\n\t\t\tvalue: period?.done ?? 0,\n\t\t\thint:\n\t\t\t\tperiod === undefined\n\t\t\t\t\t? undefined\n\t\t\t\t\t: t(\"statCreatedHint\", { n: period.created }),\n\t\t\tinteractive: false,\n\t\t\ttitle:\n\t\t\t\tperiod === undefined\n\t\t\t\t\t? undefined\n\t\t\t\t\t: t(\"periodRange\", { from: period.from, to: period.to }),\n\t\t});\n\n\tconst [chartScope, setChartScope] = useState<\"all\" | \"mine\">(\"all\");\n\tconst chartWeeks = useMemo(\n\t\t() =>\n\t\t\t(trend?.closed.weekly[chartScope] ?? []).map((bucket) => {\n\t\t\t\t// 容错:host 旧版可能不带 end(客户端/宿主版本错配时),退回用 week,绝不崩面板。\n\t\t\t\tconst end = bucket.end ?? bucket.week ?? \"\";\n\t\t\t\treturn {\n\t\t\t\t\tlabel: end.slice(5) || bucket.week?.slice(5) || \"\",\n\t\t\t\t\tdone: bucket.done,\n\t\t\t\t\tremaining: bucket.remaining,\n\t\t\t\t\tcreated: bucket.created,\n\t\t\t\t\ttitle:\n\t\t\t\t\t\tchartScope === \"mine\"\n\t\t\t\t\t\t\t? `截至 ${end}(${t(\"chartOnlyMine\")})`\n\t\t\t\t\t\t\t: `截至 ${end}`,\n\t\t\t\t};\n\t\t\t}),\n\t\t[trend, chartScope, t],\n\t);\n\tconst chartEmpty = chartWeeks.every(\n\t\t(week) => week.done === 0 && week.created === 0 && week.remaining === 0,\n\t);\n\n\treturn h(\n\t\t\"div\",\n\t\t{ style: pageStyle },\n\t\th(\n\t\t\t\"div\",\n\t\t\t{ style: { display: \"flex\", justifyContent: \"center\" } },\n\t\t\th(\n\t\t\t\t\"div\",\n\t\t\t\t{\n\t\t\t\t\tstyle: {\n\t\t\t\t\t\twidth: \"100%\",\n\t\t\t\t\t\tmaxWidth: \"1280px\",\n\t\t\t\t\t\tminWidth: 0,\n\t\t\t\t\t\tboxSizing: \"border-box\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\th(\n\t\t\t\t\t\"div\",\n\t\t\t\t\t{ style: headerStyle },\n\t\t\t\t\th(\n\t\t\t\t\t\t\"div\",\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tstyle: {\n\t\t\t\t\t\t\t\tdisplay: \"flex\",\n\t\t\t\t\t\t\t\talignItems: \"center\",\n\t\t\t\t\t\t\t\tgap: \"var(--dtl-space-3)\",\n\t\t\t\t\t\t\t\tminWidth: 0,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\th(\n\t\t\t\t\t\t\tButton,\n\t\t\t\t\t\t\t{ variant: \"outline\", size: \"md\", onClick: onBack },\n\t\t\t\t\t\t\t`← ${t(\"backToConversation\")}`,\n\t\t\t\t\t\t),\n\t\t\t\t\t\th(\"div\", { style: titleStyle }, t(\"panelTitle\")),\n\t\t\t\t\t),\n\t\t\t\t\th(\n\t\t\t\t\t\t\"div\",\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tstyle: {\n\t\t\t\t\t\t\t\tdisplay: \"flex\",\n\t\t\t\t\t\t\t\talignItems: \"center\",\n\t\t\t\t\t\t\t\tgap: \"var(--dtl-space-2)\",\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\th(Segmented<Tab>, {\n\t\t\t\t\t\t\tid: \"dtl-tab\",\n\t\t\t\t\t\t\tvalue: tab,\n\t\t\t\t\t\t\tlabel: t(\"panelTitle\"),\n\t\t\t\t\t\t\titems: [\n\t\t\t\t\t\t\t\t{ value: \"tasks\", label: t(\"tabTasks\") },\n\t\t\t\t\t\t\t\t{ value: \"stats\", label: t(\"tabStats\") },\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\tonChange: setTab,\n\t\t\t\t\t\t}),\n\t\t\t\t\t\th(\n\t\t\t\t\t\t\tButton,\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tvariant: \"outline\",\n\t\t\t\t\t\t\t\tsize: \"md\",\n\t\t\t\t\t\t\t\ticon: h(IconRefreshOutlineRegular, { size: 16 }),\n\t\t\t\t\t\t\t\tdisabled: state.refreshing,\n\t\t\t\t\t\t\t\ttitle: t(\"refresh\"),\n\t\t\t\t\t\t\t\tonClick: () => {\n\t\t\t\t\t\t\t\t\tvoid refresh();\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tstate.refreshing ? t(\"refreshing\") : t(\"refresh\"),\n\t\t\t\t\t\t),\n\t\t\t\t\t),\n\t\t\t\t),\n\n\t\t\t\ttab === \"stats\"\n\t\t\t\t\t? // 统计报表尚未开建(另立任务):占位说明,不画假图表。\n\t\t\t\t\t\th(\"div\", { style: hintStyle }, t(\"statsPlaceholder\"))\n\t\t\t\t\t: h(\n\t\t\t\t\t\t\t\"div\",\n\t\t\t\t\t\t\tnull,\n\t\t\t\t\t\t\t// ── 统计区:左 8 块(操作台 4 + 统计台 4)+ 右趋势图 ──\n\t\t\t\t\t\t\tstats === undefined\n\t\t\t\t\t\t\t\t? null\n\t\t\t\t\t\t\t\t: h(\n\t\t\t\t\t\t\t\t\t\t\"div\",\n\t\t\t\t\t\t\t\t\t\t{ className: \"dtl-stats\", style: statsRowStyle },\n\t\t\t\t\t\t\t\t\t\th(\n\t\t\t\t\t\t\t\t\t\t\t\"div\",\n\t\t\t\t\t\t\t\t\t\t\t{ className: \"dtl-stats__cards\" },\n\t\t\t\t\t\t\t\t\t\t\t// 按列成对(用户 2026-10-19 选 A):每列上下是同一对象的两个视角,\n\t\t\t\t\t\t\t\t\t\t\t// 子集关系一眼可见 —— 积压 ⊂ 待认领、逾期 / 停滞 ⊂ 进行中。\n\t\t\t\t\t\t\t\t\t\t\t// DOM 按**列序**写,CSS 的 grid-auto-flow:column 保证 4 列 / 2 列两种排布下都成对。\n\t\t\t\t\t\t\t\t\t\t\t// 小字一律给本卡独有的增量信息,**不重复全集**(用户 2026-10-19):\n\t\t\t\t\t\t\t\t\t\t\t// 三块子集卡一律报**占全集的比例**(用户 2026-10-19 二选一时定占比),0 条时整条不显示。\n\t\t\t\t\t\t\t\t\t\t\tcard(\n\t\t\t\t\t\t\t\t\t\t\t\t\"statMyActive\",\n\t\t\t\t\t\t\t\t\t\t\t\tstats.myActive,\n\t\t\t\t\t\t\t\t\t\t\t\t[\n\t\t\t\t\t\t\t\t\t\t\t\t\tstats.myOverdue > 0\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t? t(\"statMyOverdueHint\", { n: stats.myOverdue })\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t: null,\n\t\t\t\t\t\t\t\t\t\t\t\t\tstats.myStale > 0\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t? t(\"statMyStaleHint\", { n: stats.myStale })\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t: null,\n\t\t\t\t\t\t\t\t\t\t\t\t]\n\t\t\t\t\t\t\t\t\t\t\t\t\t.filter((part) => part !== null)\n\t\t\t\t\t\t\t\t\t\t\t\t\t.join(\" | \"),\n\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t\tcard(\n\t\t\t\t\t\t\t\t\t\t\t\t\"statDoing\",\n\t\t\t\t\t\t\t\t\t\t\t\tstats.doing,\n\t\t\t\t\t\t\t\t\t\t\t\tstats.doing - stats.myActive > 0\n\t\t\t\t\t\t\t\t\t\t\t\t\t? t(\"statDoingHint\", {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tn: stats.doing - stats.myActive,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t\t\t\t\t\t\t: t(\"statDoingAllMine\"),\n\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t\tcard(\n\t\t\t\t\t\t\t\t\t\t\t\t\"statOpen\",\n\t\t\t\t\t\t\t\t\t\t\t\tstats.open,\n\t\t\t\t\t\t\t\t\t\t\t\tstats.oldestOpenDays === null\n\t\t\t\t\t\t\t\t\t\t\t\t\t? \"\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t: t(\"statOpenHint\", { n: stats.oldestOpenDays }),\n\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t\tcard(\n\t\t\t\t\t\t\t\t\t\t\t\t\"statBacklog\",\n\t\t\t\t\t\t\t\t\t\t\t\tstats.backlog,\n\t\t\t\t\t\t\t\t\t\t\t\tshare(stats.backlog, stats.open, \"statBacklogHint\"),\n\t\t\t\t\t\t\t\t\t\t\t\tt(\"statBacklogTitle\", { n: stats.backlogDays }),\n\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t\tcard(\n\t\t\t\t\t\t\t\t\t\t\t\t\"statOverdue\",\n\t\t\t\t\t\t\t\t\t\t\t\tstats.overdue,\n\t\t\t\t\t\t\t\t\t\t\t\tshare(stats.overdue, stats.doing, \"statOverdueHint\"),\n\t\t\t\t\t\t\t\t\t\t\t\tt(\"statOverdueTitle\", { n: stats.overdueDays }),\n\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t\tcard(\n\t\t\t\t\t\t\t\t\t\t\t\t\"statStale\",\n\t\t\t\t\t\t\t\t\t\t\t\tstats.stale,\n\t\t\t\t\t\t\t\t\t\t\t\tshare(stats.stale, stats.doing, \"statStaleHint\"),\n\t\t\t\t\t\t\t\t\t\t\t\tt(\"statStaleTitle\", { n: stats.staleDays }),\n\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t\tperiodCard(\"statWeekDone\", periods?.thisWeek),\n\t\t\t\t\t\t\t\t\t\t\tperiodCard(\"statLastWeekDone\", periods?.lastWeek),\n\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\th(\n\t\t\t\t\t\t\t\t\t\t\t\"div\",\n\t\t\t\t\t\t\t\t\t\t\t{ className: \"dtl-card\", style: chartCardStyle },\n\t\t\t\t\t\t\t\t\t\t\t// 右上角只留一个「只看我的」小复选框:勾上 = 我的,不勾 = 所有(用户 2026-10-17)\n\t\t\t\t\t\t\t\t\t\t\th(\n\t\t\t\t\t\t\t\t\t\t\t\t\"div\",\n\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\tstyle: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tdisplay: \"flex\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\talignItems: \"center\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tjustifyContent: \"flex-end\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\th(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"label\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t{ className: \"dtl-check\" },\n\t\t\t\t\t\t\t\t\t\t\t\t\th(\"input\", {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"checkbox\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tchecked: chartScope === \"mine\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tonChange: (\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tevent: ChangeEvent<HTMLInputElement>,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t) => {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tsetChartScope(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tevent.target.checked ? \"mine\" : \"all\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t\t\t\t\t\t\tt(\"chartOnlyMine\"),\n\t\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t\t// 趋势是慢路径:未到给占位、读挂给兜底文案(带原因),就绪才画图——绝不画空图冒充「没有记录」。\n\t\t\t\t\t\t\t\t\t\t\ttrendPending\n\t\t\t\t\t\t\t\t\t\t\t\t? h(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"div\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tstyle: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t...hintStyle,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tpadding: \"var(--dtl-space-4) 0\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tt(\"chartLoading\"),\n\t\t\t\t\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\t\t\t\t: state.trendStatus === \"error\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t? h(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"div\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tstyle: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t...hintStyle,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tpadding: \"var(--dtl-space-4) 0\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t`${t(\"chartUnavailable\")}${state.trendError === null ? \"\" : `:${state.trendError}`}`,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\t\t\t\t\t: chartEmpty\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t? h(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"div\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tstyle: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t...hintStyle,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tpadding: \"var(--dtl-space-4) 0\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tt(\"chartEmpty\"),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t: h(GroupedBarChart, {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tweeks: chartWeeks,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tariaLabel: t(\"chartTitle\"),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tdoneLabel: t(\"chartLegendDone\"),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tremainingLabel: t(\"chartLegendRemaining\"),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tcreatedLabel: t(\"chartLegendCreated\"),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t\t\t\t\th(ChartLegend, {\n\t\t\t\t\t\t\t\t\t\t\t\tdoneLabel: t(\"chartLegendDone\"),\n\t\t\t\t\t\t\t\t\t\t\t\tremainingLabel: t(\"chartLegendRemaining\"),\n\t\t\t\t\t\t\t\t\t\t\t\tcreatedLabel: t(\"chartLegendCreated\"),\n\t\t\t\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t),\n\n\t\t\t\t\t\t\t// ── 列表 ──\n\t\t\t\t\t\t\tstate.status === \"loading\" && board === null\n\t\t\t\t\t\t\t\t? null // 未就绪:不渲染\n\t\t\t\t\t\t\t\t: state.status === \"error\" && board === null\n\t\t\t\t\t\t\t\t\t? h(\n\t\t\t\t\t\t\t\t\t\t\t\"div\",\n\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\tstyle: {\n\t\t\t\t\t\t\t\t\t\t\t\t\tdisplay: \"flex\",\n\t\t\t\t\t\t\t\t\t\t\t\t\talignItems: \"center\",\n\t\t\t\t\t\t\t\t\t\t\t\t\tgap: \"var(--dtl-space-2)\",\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\th(\n\t\t\t\t\t\t\t\t\t\t\t\t\"span\",\n\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\tstyle: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tcolor: \"var(--dtl-danger)\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tfontSize: \"var(--dtl-font-md)\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t`${t(\"loadFailed\")}:${state.error ?? \"\"}`,\n\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t\th(\n\t\t\t\t\t\t\t\t\t\t\t\tButton,\n\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\tvariant: \"outline\",\n\t\t\t\t\t\t\t\t\t\t\t\t\tsize: \"sm\",\n\t\t\t\t\t\t\t\t\t\t\t\t\tonClick: () => {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tvoid refresh();\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\tt(\"retry\"),\n\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\t: board !== null && board.workspaces.length === 0\n\t\t\t\t\t\t\t\t\t\t? h(EmptyState, {\n\t\t\t\t\t\t\t\t\t\t\t\ttone: \"guide\",\n\t\t\t\t\t\t\t\t\t\t\t\ttitle: t(\"emptyNoWorkspace\"),\n\t\t\t\t\t\t\t\t\t\t\t\thint: t(\"emptyNoWorkspaceHint\"),\n\t\t\t\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t\t\t\t: h(\n\t\t\t\t\t\t\t\t\t\t\t\t\"div\",\n\t\t\t\t\t\t\t\t\t\t\t\tnull,\n\t\t\t\t\t\t\t\t\t\t\t\t// 降级横幅:有工作区读挂 ⇒ 红色警告 + 人话原因(单工作区坏不拖垮其余,别装没看见)\n\t\t\t\t\t\t\t\t\t\t\t\tboard !== null && (board.degraded?.length ?? 0) > 0\n\t\t\t\t\t\t\t\t\t\t\t\t\t? h(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"div\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tstyle: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tdisplay: \"flex\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\talignItems: \"flex-start\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tgap: \"var(--dtl-space-2)\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tpadding:\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"var(--dtl-space-2) var(--dtl-space-3)\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tmarginBottom: \"var(--dtl-space-3)\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tborder: \"1px solid var(--dtl-danger)\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tborderRadius: \"var(--dtl-radius-md)\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tbackground: \"var(--dtl-danger-soft)\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tcolor: \"var(--dtl-fg)\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tfontSize: \"var(--dtl-font-sm)\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tlineHeight: \"var(--dtl-line-sm)\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\th(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"span\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tstyle: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tcolor: \"var(--dtl-danger)\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tflex: \"none\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tfontWeight: 600,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tt(\"degradedTitle\"),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\th(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"span\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tnull,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tdegraded\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t.map((item) =>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tt(\"degradedItem\", {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ttitle: item.workspaceTitle,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tmessage: item.message,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t.join(\";\"),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\t\t\t\t\t: null,\n\t\t\t\t\t\t\t\t\t\t\t\t// 第一区:我的待办——定死全量、不过滤(用户 2026-10-17),空了给引导卡;\n\t\t\t\t\t\t\t\t\t\t\t\t// 标题行右侧挂搜索框(只作用第三区),计数用小圆徽\n\t\t\t\t\t\t\t\t\t\t\t\th(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"div\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t{ style: regionHeadRowStyle },\n\t\t\t\t\t\t\t\t\t\t\t\t\th(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"span\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tstyle: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tcolor: \"var(--dtl-fg-3)\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tdisplay: \"inline-flex\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tflex: \"none\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\th(IconChecklistOutlineRegular, { size: 16 }),\n\t\t\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t\t\t\th(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"span\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t{ style: regionHeadTitleStyle },\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tt(\"regionMine\"),\n\t\t\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t\t\t\tview.mine.length > 0\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t? h(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"span\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t{ className: \"dtl-count\" },\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tt(\"mineCount\", { n: view.mine.length }),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t: null,\n\t\t\t\t\t\t\t\t\t\t\t\t\th(\"span\", { style: { flex: \"1 1 auto\" } }),\n\t\t\t\t\t\t\t\t\t\t\t\t\t// 工作区下拉:内容自适应、下限 131(用户 2026-10-17)\n\t\t\t\t\t\t\t\t\t\t\t\t\th(Select<string>, {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tvalue: workspaceOptions.some(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t(option) =>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\toption.value === state.query.workspace,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t? state.query.workspace\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t: \"\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\toptions: workspaceOptions,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tariaLabel: t(\"workspaceLabel\"),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tminWidth: WORKSPACE_SELECT_MIN,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tonChange: (next) => {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tsetQuery({ workspace: next });\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t\t\t\t\t\t\t// 搜索框:在下拉右边、与「其他待办」同宽 192(用户 2026-10-17)\n\t\t\t\t\t\t\t\t\t\t\t\t\th(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"div\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tstyle: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\twidth: `${SEARCH_WIDTH}px`,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tflex: \"none\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\th(SearchInput, {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tvalue: state.query.keyword,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tplaceholder: t(\"searchPlaceholder\"),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tariaLabel: t(\"searchPlaceholder\"),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tonChange: (next) => {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tsetQuery({ keyword: next });\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t\t\tview.mine.length === 0\n\t\t\t\t\t\t\t\t\t\t\t\t\t? h(EmptyState, {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ttone: \"guide\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ttitle: t(\"mineEmpty\"),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\thint: t(\"mineEmptyHint\"),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t\t\t\t\t\t\t: view.mine.map((row) =>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\th(TaskRowView, {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tkey: row.key,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tt,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\trow,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tvariant: \"mine\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tboard,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t\t\t// 第二区:全部待办 —— **永远渲染**(用户 2026-10-18:选「进行中」没数据也不能整块消失;\n\t\t\t\t\t\t\t\t\t\t\t\t// 且不要过滤掉自己,所以含我的任务,会与第一区重叠——顶部快看 / 底部全量);\n\t\t\t\t\t\t\t\t\t\t\t\t// 标题行:图标 + 名 + 状态滑轨(带全量角标)+ 搜索(最右);表格区无数据给虚线空态\n\t\t\t\t\t\t\t\t\t\t\t\th(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"div\",\n\t\t\t\t\t\t\t\t\t\t\t\t\tnull,\n\t\t\t\t\t\t\t\t\t\t\t\t\th(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"div\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t{ style: regionHeadRowStyle },\n\t\t\t\t\t\t\t\t\t\t\t\t\t\th(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"span\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tstyle: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tcolor: \"var(--dtl-fg-3)\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tdisplay: \"inline-flex\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tflex: \"none\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\th(IconFlatListOutlineRegular, { size: 16 }),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\th(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"span\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tstyle: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t...regionHeadTitleStyle,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tfontSize: \"var(--dtl-font-md)\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tt(\"regionAll\"),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\th(\"span\", { style: { flex: \"1 1 auto\" } }),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t// 状态滑轨:角标 = 第二区**全量**计数(不受滑轨自身影响);0 不标数字\n\t\t\t\t\t\t\t\t\t\t\t\t\t\th(Segmented<StatusFilter>, {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tid: \"dtl-others-status\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tvalue: state.query.status,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tlabel: t(\"statusLabel\"),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\titems: [\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tvalue: \"all\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tlabel: t(\"statusAll\"),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tbadge: orZero(view.allCounts.total),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tvalue: \"active\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tlabel: t(\"statusActive\"),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tbadge: orZero(view.allCounts.doing),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tvalue: \"open\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tlabel: t(\"statusOpen\"),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tbadge: orZero(view.allCounts.open),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tvalue: \"backlog\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tlabel: t(\"statusBacklog\"),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tbadge: orZero(view.allCounts.backlog),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tvalue: \"overdue\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tlabel: t(\"statusOverdue\"),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tbadge: orZero(view.allCounts.overdue),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tvalue: \"stale\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tlabel: t(\"statusStale\"),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tbadge: orZero(view.allCounts.stale),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tonChange: (next) => {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tsetQuery({ status: next });\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\th(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"div\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tstyle: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\twidth: `${SEARCH_WIDTH}px`,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tflex: \"none\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\th(SearchInput, {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tvalue: state.query.othersKeyword,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tplaceholder: t(\"searchPlaceholder\"),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tariaLabel: t(\"searchPlaceholder\"),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tonChange: (next) => {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tsetQuery({ othersKeyword: next });\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t\t\t\tview.groups.length === 0\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t? // 空态:虚线框 + 两排字 + 按钮(参考 dispatch 空态;按钮先接「回会话」,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// 真正的「起会话建任务」归会话交接任务)\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\th(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"div\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tclassName: \"dtl-empty-guide\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tstyle: { marginTop: \"var(--dtl-space-2)\" },\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\th(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"div\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tstyle: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tfontSize: \"var(--dtl-font-lg)\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tfontWeight: 600,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tmarginBottom: \"var(--dtl-space-1)\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tt(\"allEmptyTitle\"),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\th(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"div\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tstyle: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tfontSize: \"var(--dtl-font-md)\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tcolor: \"var(--dtl-fg-2)\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tmarginBottom: \"var(--dtl-space-3)\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tt(\"allEmptyHint\"),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\th(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tButton,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tvariant: \"primary\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tsize: \"md\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tonClick: onBack,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tt(\"allEmptyAction\"),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t: h(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"div\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t{ style: { marginTop: \"var(--dtl-space-2)\" } },\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tview.groups.map((group) =>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\th(WorkspaceGroupView, {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tkey: group.workspaceId,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tt,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tgroup,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tboard,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t),\n\t\t\t),\n\t\t),\n\t);\n}\n\n/** 角标:>0 才给数字,0 = undefined(不标)。 */\nfunction orZero(n: number): number | undefined {\n\treturn n > 0 ? n : undefined;\n}\n\n/** 一个工作区分组(全部待办表格段):段头(点+名+统计)→ 列头行 → 任务行。\n * 统计口径(用户 2026-10-18):共 N|待办 N|进行中 N 常显(0 也显);\n * 积压 / 逾期 / 停滞**只在 >0 时出现**。 */\nfunction WorkspaceGroupView(props: {\n\tt: Translate;\n\tgroup: WorkspaceGroup;\n\t/** 传下去只为问动作权限(是不是我的)——第二区含我的任务,按钮得跟第一区一致。 */\n\tboard: BoardPayload | null;\n}): ReactNode {\n\tconst { t, group, board } = props;\n\tconst [open, setOpen] = useState(group.rows.length <= GROUP_COLLAPSE_OVER);\n\tconst stats = [\n\t\tt(\"groupTotal\", { n: group.total }),\n\t\tt(\"groupOpen\", { n: group.openCount }),\n\t\tt(\"groupDoing\", { n: group.doingCount }),\n\t\t...(group.backlogCount > 0\n\t\t\t? [t(\"groupBacklog\", { n: group.backlogCount })]\n\t\t\t: []),\n\t\t...(group.overdueCount > 0\n\t\t\t? [t(\"groupOverdue\", { n: group.overdueCount })]\n\t\t\t: []),\n\t\t...(group.staleCount > 0 ? [t(\"groupStale\", { n: group.staleCount })] : []),\n\t].join(\" | \");\n\treturn h(\n\t\t\"div\",\n\t\t{ className: \"dtl-group\" },\n\t\th(\n\t\t\t\"button\",\n\t\t\t{\n\t\t\t\ttype: \"button\",\n\t\t\t\tclassName: \"dtl-group__head\",\n\t\t\t\t\"aria-expanded\": open,\n\t\t\t\ttitle: open ? t(\"collapseAria\") : t(\"expandAria\"),\n\t\t\t\tonClick: () => {\n\t\t\t\t\tsetOpen(!open);\n\t\t\t\t},\n\t\t\t},\n\t\t\t// 段头标识:展开 = 打开的文件夹、收起 = 合上的文件夹(跟官方工作区显示逻辑一致);\n\t\t\t// 包里没有这对图标 ⇒ 回落成竖线\n\t\t\tIconFolderOpenRegular === undefined ||\n\t\t\t\tIconFolderCloseRegular === undefined\n\t\t\t\t? h(\"span\", { className: \"dtl-group__bar\" })\n\t\t\t\t: h(\n\t\t\t\t\t\t\"span\",\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tstyle: {\n\t\t\t\t\t\t\t\tdisplay: \"inline-flex\",\n\t\t\t\t\t\t\t\tflex: \"none\",\n\t\t\t\t\t\t\t\tcolor: \"var(--dtl-fg-3)\",\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\th(open ? IconFolderOpenRegular : IconFolderCloseRegular, {\n\t\t\t\t\t\t\tsize: 14,\n\t\t\t\t\t\t}),\n\t\t\t\t\t),\n\t\t\th(\"span\", { className: \"dtl-group__name dtl-ellipsis\" }, group.title),\n\t\t\th(\"span\", { style: { flex: \"1 1 auto\" } }),\n\t\t\th(\"span\", { className: \"dtl-group__stats\" }, stats),\n\t\t),\n\t\topen\n\t\t\t? h(\n\t\t\t\t\t\"div\",\n\t\t\t\t\tnull,\n\t\t\t\t\t// 无列头行(用户 2026-10-18:表头就是段头——左工作区名、右统计,不放「任务/创建人」那排)\n\t\t\t\t\tgroup.rows.map((row) =>\n\t\t\t\t\t\th(TaskRowView, {\n\t\t\t\t\t\t\tkey: row.key,\n\t\t\t\t\t\t\tt,\n\t\t\t\t\t\t\trow,\n\t\t\t\t\t\t\tvariant: \"others\",\n\t\t\t\t\t\t\tboard,\n\t\t\t\t\t\t}),\n\t\t\t\t\t),\n\t\t\t\t)\n\t\t\t: null,\n\t);\n}\n","/**\n * 文案唯一真源:命名空间 `dsh-task-ledger`,zh / en 两档。\n *\n * 规矩(docs/design/ui-style.md §五):\n * - 两档**键必须完全对齐**(冒烟有断言),漏一种语言界面就露键名;\n * - 界面上不许出现未登记的硬编码中文;\n * - 占位符一律 `{name}`,由 `interpolateTranslate` 自己替换(不依赖宿主是否支持 params);\n * - 语言切换**跟随宿主**:插件不自备语言开关(注册字典 + 注册项声明 `locale:` ⇒ 宿主渲染器合成 `t` 席位)。\n */\n\n/** 文案键全集(增删键必须同时改 zh / en)。 */\nexport type LocaleKey =\n\t| \"backToConversation\"\n\t| \"panelTitle\"\n\t| \"tabTasks\"\n\t| \"tabStats\"\n\t| \"refresh\"\n\t| \"refreshing\"\n\t| \"loading\"\n\t| \"retry\"\n\t| \"loadFailed\"\n\t| \"degradedTitle\"\n\t| \"degradedItem\"\n\t| \"statsPlaceholder\"\n\t// 统计卡\n\t| \"statMyActive\"\n\t| \"statOpen\"\n\t| \"statOpenHint\"\n\t| \"statDoing\"\n\t| \"statDoingHint\"\n\t| \"statDoingAllMine\"\n\t| \"statBacklog\"\n\t| \"statOverdue\"\n\t| \"statStale\"\n\t| \"statMyOverdueHint\"\n\t| \"statMyStaleHint\"\n\t| \"statBacklogHint\"\n\t| \"statOverdueHint\"\n\t| \"statStaleHint\"\n\t| \"statStaleTitle\"\n\t| \"statOverdueTitle\"\n\t| \"statBacklogTitle\"\n\t| \"statWeekDone\"\n\t| \"statLastWeekDone\"\n\t| \"statCreatedHint\"\n\t| \"daysNone\"\n\t| \"daysValue\"\n\t// 趋势图\n\t| \"chartTitle\"\n\t| \"chartCaption\"\n\t| \"chartBucket\"\n\t| \"chartEmpty\"\n\t| \"chartLoading\"\n\t| \"chartUnavailable\"\n\t| \"chartScopeAll\"\n\t| \"chartScopeMine\"\n\t| \"chartOnlyMine\"\n\t| \"chartLegendDone\"\n\t| \"chartLegendCreated\"\n\t| \"chartLegendRemaining\"\n\t| \"chartAvg\"\n\t| \"periodRange\"\n\t// 筛选行\n\t| \"scopeLabel\"\n\t| \"scopeMine\"\n\t| \"scopeAll\"\n\t| \"statusLabel\"\n\t| \"statusAll\"\n\t| \"statusActive\"\n\t| \"statusOpen\"\n\t| \"statusBacklog\"\n\t| \"statusOverdue\"\n\t| \"statusStale\"\n\t| \"tipOpen\"\n\t| \"tipBacklog\"\n\t| \"tipDoing\"\n\t| \"tipOverdue\"\n\t| \"tipStale\"\n\t| \"workspaceLabel\"\n\t| \"workspaceAll\"\n\t| \"searchPlaceholder\"\n\t// 列表分区\n\t| \"regionMine\"\n\t| \"regionAll\"\n\t| \"showingCount\"\n\t| \"groupTotal\"\n\t| \"groupOpen\"\n\t| \"groupDoing\"\n\t| \"groupBacklog\"\n\t| \"groupOverdue\"\n\t| \"groupStale\"\n\t| \"colTask\"\n\t| \"colCreator\"\n\t| \"colOwner\"\n\t| \"colStatus\"\n\t| \"colTime\"\n\t| \"allEmptyTitle\"\n\t| \"allEmptyHint\"\n\t| \"allEmptyAction\"\n\t| \"expandAria\"\n\t| \"collapseAria\"\n\t| \"ownerUnclaimed\"\n\t| \"fieldCreator\"\n\t| \"fieldOwner\"\n\t| \"fieldCreated\"\n\t| \"fieldStarted\"\n\t| \"fieldFinished\"\n\t| \"timeUnknown\"\n\t| \"ageDaysText\"\n\t| \"ageToday\"\n\t| \"startedAt\"\n\t| \"actionResume\"\n\t| \"actionFinish\"\n\t| \"actionRelease\"\n\t| \"actionClaim\"\n\t| \"tipResume\"\n\t| \"tipFinish\"\n\t| \"tipRelease\"\n\t| \"tipClaim\"\n\t| \"viewDetail\"\n\t| \"createdAt\"\n\t| \"fieldCreatedStamp\"\n\t| \"mineEmpty\"\n\t| \"mineEmptyHint\"\n\t| \"mineCount\"\n\t| \"worklogTitle\"\n\t| \"worklogPath\"\n\t| \"worklogMissing\"\n\t| \"mdCopy\"\n\t| \"mdCopied\"\n\t| \"mdFootnotes\"\n\t// 空态\n\t| \"emptyNoWorkspace\"\n\t| \"emptyNoWorkspaceHint\"\n\t| \"emptyNoTask\"\n\t| \"emptyNoTaskHint\"\n\t| \"emptyFiltered\"\n\t// 浮标入口\n\t| \"badgeTitle\"\n\t| \"openBoard\";\n\n/** 中文(默认档)。 */\nexport const zh: Record<LocaleKey, string> = {\n\tbackToConversation: \"返回会话\",\n\tpanelTitle: \"任务台账\",\n\ttabTasks: \"任务\",\n\ttabStats: \"统计\",\n\trefresh: \"刷新\",\n\trefreshing: \"刷新中\",\n\tloading: \"读取中…\",\n\tretry: \"重试\",\n\tloadFailed: \"读取失败\",\n\tdegradedTitle: \"部分工作区读取失败\",\n\tdegradedItem: \"{title}:{message}\",\n\tstatsPlaceholder:\n\t\t\"统计报表尚未开建(另立任务):这里以后放分类分布、按人完成数、时间线。\",\n\n\tstatMyActive: \"我的待办\",\n\tstatMyOverdueHint: \"逾期 {n}\",\n\tstatMyStaleHint: \"停滞 {n}\",\n\tstatOpen: \"待认领\",\n\tstatOpenHint: \"最长等待 {n} 天\",\n\tstatDoing: \"进行中\",\n\tstatDoingHint: \"他人在办 {n}\",\n\tstatDoingAllMine: \"均为我负责\",\n\tstatBacklog: \"积压\",\n\tstatOverdue: \"逾期\",\n\tstatStale: \"停滞\",\n\tstatBacklogHint: \"占待认领 {n}%\",\n\tstatOverdueHint: \"占进行中 {n}%\",\n\tstatStaleHint: \"占进行中 {n}%\",\n\tstatStaleTitle: \"停滞 = 进行中满 {n} 天没更新\",\n\tstatOverdueTitle: \"逾期 = 认领后满 {n} 天还没结案\",\n\tstatBacklogTitle: \"积压 = 待认领满 {n} 天没人接\",\n\tstatWeekDone: \"本周完成\",\n\tstatLastWeekDone: \"上周完成\",\n\tstatCreatedHint: \"新增 {n}\",\n\tdaysNone: \"—\",\n\tdaysValue: \"{n} 天\",\n\n\tchartTitle: \"近 8 周\",\n\tchartCaption:\n\t\t\"完成(按结案时间)/ 新增(按创建时间),周一起桶;我的 = owner 是我\",\n\tchartBucket: \"{week} 当周:完成 {done} 条,新增 {created} 条\",\n\tchartEmpty: \"近 8 周没有记录\",\n\tchartLoading: \"趋势读取中…(列表已就绪,统计稍后到)\",\n\tchartUnavailable: \"趋势暂时读不到(不影响上面的任务列表)\",\n\tchartScopeAll: \"所有\",\n\tchartScopeMine: \"我的\",\n\tchartOnlyMine: \"只看我的\",\n\tchartLegendDone: \"完成\",\n\tchartLegendCreated: \"新增\",\n\tchartLegendRemaining: \"未结\",\n\tchartAvg: \"周均 {n}\",\n\tperiodRange: \"{from} ~ {to}\",\n\n\tscopeLabel: \"范围\",\n\tscopeMine: \"我的\",\n\tscopeAll: \"全部工作区\",\n\tstatusLabel: \"状态\",\n\tstatusAll: \"全部\",\n\tstatusActive: \"进行中\",\n\tstatusOpen: \"待认领\",\n\tstatusBacklog: \"积压\",\n\tstatusOverdue: \"逾期\",\n\tstatusStale: \"停滞\",\n\ttipOpen: \"任务创建于 {created}\\n尚未有人认领\",\n\ttipBacklog: \"任务创建于 {created}\\n无人认领已满 {d}\",\n\ttipDoing: \"{who}\\n开始执行:{started}\\n最后更新:{updated}\",\n\ttipOverdue: \"{who}\\n开始执行:{started}\\n最后更新:{updated}\\n已逾期 {d}\",\n\ttipStale: \"{who}\\n开始执行:{started}\\n最后更新:{updated}\\n已停滞 {d}\",\n\tworkspaceLabel: \"工作区\",\n\tworkspaceAll: \"全部工作区\",\n\tsearchPlaceholder: \"搜索\",\n\n\tregionMine: \"我的待办\",\n\tregionAll: \"全部待办\",\n\tshowingCount: \"显示 {n} 条\",\n\tgroupTotal: \"共 {n} 条\",\n\tgroupOpen: \"待办 {n} 条\",\n\tgroupDoing: \"进行中 {n} 条\",\n\tgroupBacklog: \"积压 {n} 条\",\n\tgroupOverdue: \"逾期 {n} 条\",\n\tgroupStale: \"停滞 {n} 条\",\n\tcolTask: \"任务\",\n\tcolCreator: \"创建人\",\n\tcolOwner: \"执行人\",\n\tcolStatus: \"状态\",\n\tcolTime: \"时长\",\n\tallEmptyTitle: \"没有可显示的事项\",\n\tallEmptyHint: \"切换上面的状态过滤试试,或新建一个任务。\",\n\tallEmptyAction: \"新建任务\",\n\texpandAria: \"展开过程文档\",\n\tcollapseAria: \"收起\",\n\n\townerUnclaimed: \"待认领\",\n\tfieldCreator: \"创建\",\n\tfieldOwner: \"执行\",\n\tfieldCreated: \"创建\",\n\tfieldStarted: \"开始\",\n\tfieldFinished: \"结案\",\n\ttimeUnknown: \"时间未知\",\n\tageDaysText: \"已进行 {n} 天\",\n\tageToday: \"今天\",\n\tactionResume: \"继续\",\n\tactionFinish: \"结束\",\n\tactionRelease: \"释放\",\n\ttipResume: \"继续推进这个任务\",\n\ttipFinish: \"结案并写入历史\",\n\ttipRelease: \"释放认领,让别人接手\",\n\tactionClaim: \"认领\",\n\ttipClaim: \"认领这个任务,变成我在做\",\n\tcreatedAt: \"{who} 创建于 {when}\",\n\tstartedAt: \"{who} 开始于 {when}\",\n\tviewDetail: \"查看详情\",\n\tfieldCreatedStamp: \"{day} 创建\",\n\tmineEmpty: \"您现在没有正在进行的工作\",\n\tmineEmptyHint:\n\t\t\"在某个工作区 new 一个任务,或到下面认领一条待认领任务,这里就会出现。\",\n\tmineCount: \"{n} 条\",\n\tworklogTitle: \"过程文档\",\n\tworklogPath: \"路径\",\n\tworklogMissing: \"(缺失)\",\n\tmdCopy: \"复制\",\n\tmdCopied: \"已复制\",\n\tmdFootnotes: \"脚注\",\n\n\temptyNoWorkspace: \"还没有台账工作区\",\n\temptyNoWorkspaceHint:\n\t\t\"在某个项目里跑一条 task-ledger skill 的写命令(第一条会自动建档 ledger/pool.json),这里就会出现它。\",\n\temptyNoTask: \"一条任务都没有\",\n\temptyNoTaskHint:\n\t\t\"用 task-ledger skill 的 new 开一个任务,或让别人开在这里等你认领。\",\n\temptyFiltered: \"没有符合当前筛选的任务\",\n\n\tbadgeTitle: \"我名下待办\",\n\topenBoard: \"打开任务台账\",\n};\n\n/** English(与 zh 键完全对齐)。 */\nexport const en: Record<LocaleKey, string> = {\n\tbackToConversation: \"Back to chat\",\n\tpanelTitle: \"Task ledger\",\n\ttabTasks: \"Tasks\",\n\ttabStats: \"Stats\",\n\trefresh: \"Refresh\",\n\trefreshing: \"Refreshing\",\n\tloading: \"Loading…\",\n\tretry: \"Retry\",\n\tloadFailed: \"Load failed\",\n\tdegradedTitle: \"Some workspaces failed to load\",\n\tdegradedItem: \"{title}: {message}\",\n\tstatsPlaceholder:\n\t\t\"Stats reports are not built yet (separate task): category breakdown, completions by person, timeline.\",\n\n\tstatMyActive: \"My todos\",\n\tstatMyOverdueHint: \"overdue {n}\",\n\tstatMyStaleHint: \"stale {n}\",\n\tstatOpen: \"Unclaimed\",\n\tstatOpenHint: \"longest waiting {n} days\",\n\tstatDoing: \"In progress\",\n\tstatDoingHint: \"others: {n}\",\n\tstatDoingAllMine: \"all mine\",\n\tstatBacklog: \"Backlog\",\n\tstatOverdue: \"Overdue\",\n\tstatStale: \"Stale\",\n\tstatBacklogHint: \"{n}% of unclaimed\",\n\tstatOverdueHint: \"{n}% of active\",\n\tstatStaleHint: \"{n}% of active\",\n\tstatStaleTitle: \"stale = active with no update for {n}+ days\",\n\tstatOverdueTitle: \"overdue = claimed {n}+ days ago and still open\",\n\tstatBacklogTitle: \"backlog = unclaimed for {n}+ days\",\n\tstatWeekDone: \"Done this week\",\n\tstatLastWeekDone: \"Done last week\",\n\tstatCreatedHint: \"{n} created\",\n\tdaysNone: \"—\",\n\tdaysValue: \"{n}d\",\n\n\tchartTitle: \"Last 8 weeks\",\n\tchartCaption:\n\t\t\"done (by close time) / created (by create time), weeks start Monday; mine = owner is me\",\n\tchartBucket: \"week of {week}: {done} done, {created} created\",\n\tchartEmpty: \"Nothing in the last 8 weeks\",\n\tchartLoading: \"Loading trend… (list is ready, stats will follow)\",\n\tchartUnavailable:\n\t\t\"Trend is unavailable right now (the task lists above are unaffected)\",\n\tchartScopeAll: \"All\",\n\tchartScopeMine: \"Mine\",\n\tchartOnlyMine: \"Mine only\",\n\tchartLegendDone: \"Done\",\n\tchartLegendCreated: \"Created\",\n\tchartLegendRemaining: \"Outstanding\",\n\tchartAvg: \"avg {n}/wk\",\n\tperiodRange: \"{from} ~ {to}\",\n\n\tscopeLabel: \"Scope\",\n\tscopeMine: \"Mine\",\n\tscopeAll: \"All workspaces\",\n\tstatusLabel: \"Status\",\n\tstatusAll: \"All\",\n\tstatusActive: \"Active\",\n\tstatusOpen: \"Unclaimed\",\n\tstatusBacklog: \"Backlog\",\n\tstatusOverdue: \"Overdue\",\n\tstatusStale: \"Stale\",\n\ttipOpen: \"Created on {created}\\nNot claimed yet\",\n\ttipBacklog: \"Created on {created}\\nUnclaimed for {d}\",\n\ttipDoing: \"{who}\\nStarted: {started}\\nLast updated: {updated}\",\n\ttipOverdue:\n\t\t\"{who}\\nStarted: {started}\\nLast updated: {updated}\\nOverdue by {d}\",\n\ttipStale:\n\t\t\"{who}\\nStarted: {started}\\nLast updated: {updated}\\nStalled for {d}\",\n\tworkspaceLabel: \"Workspace\",\n\tworkspaceAll: \"All workspaces\",\n\tsearchPlaceholder: \"Search\",\n\n\tregionMine: \"My todos\",\n\tregionAll: \"All tasks\",\n\tshowingCount: \"{n} shown\",\n\tgroupTotal: \"{n} total\",\n\tgroupOpen: \"{n} open\",\n\tgroupDoing: \"{n} active\",\n\tgroupBacklog: \"{n} backlog\",\n\tgroupOverdue: \"{n} overdue\",\n\tgroupStale: \"{n} stale\",\n\tcolTask: \"Task\",\n\tcolCreator: \"Created by\",\n\tcolOwner: \"Owner\",\n\tcolStatus: \"Status\",\n\tcolTime: \"Duration\",\n\tallEmptyTitle: \"Nothing to show\",\n\tallEmptyHint: \"Try another status filter above, or create a task.\",\n\tallEmptyAction: \"New task\",\n\texpandAria: \"Expand worklog\",\n\tcollapseAria: \"Collapse\",\n\n\townerUnclaimed: \"unclaimed\",\n\tfieldCreator: \"created by\",\n\tfieldOwner: \"owner\",\n\tfieldCreated: \"created\",\n\tfieldStarted: \"started\",\n\tfieldFinished: \"closed\",\n\ttimeUnknown: \"unknown time\",\n\tageDaysText: \"active {n}d\",\n\tageToday: \"today\",\n\tactionResume: \"Resume\",\n\tactionFinish: \"Close\",\n\tactionRelease: \"Release\",\n\ttipResume: \"keep working on this task\",\n\ttipFinish: \"close and archive it\",\n\ttipRelease: \"release the claim for others\",\n\tactionClaim: \"Claim\",\n\ttipClaim: \"claim this task for yourself\",\n\tcreatedAt: \"created by {who} on {when}\",\n\tstartedAt: \"{who} started on {when}\",\n\tviewDetail: \"View details\",\n\tfieldCreatedStamp: \"created {day}\",\n\tmineEmpty: \"Nothing in progress right now\",\n\tmineEmptyHint:\n\t\t\"Create a task in a workspace or claim one below, and it shows up here.\",\n\tmineCount: \"{n} items\",\n\tworklogTitle: \"Worklog\",\n\tworklogPath: \"path\",\n\tworklogMissing: \"(missing)\",\n\tmdCopy: \"Copy\",\n\tmdCopied: \"Copied\",\n\tmdFootnotes: \"Footnotes\",\n\n\temptyNoWorkspace: \"No ledger workspace yet\",\n\temptyNoWorkspaceHint:\n\t\t\"Run any task-ledger skill write command in a project (the first one creates ledger/pool.json) and it shows up here.\",\n\temptyNoTask: \"No tasks yet\",\n\temptyNoTaskHint:\n\t\t\"Create one with the task-ledger skill new, or leave one here for others to claim.\",\n\temptyFiltered: \"No tasks match the current filters\",\n\n\tbadgeTitle: \"my todos\",\n\topenBoard: \"Open task ledger\",\n};\n\n/** 翻译函数类型(宿主渲染器按 `locale:` 声明合成的 `t` 席位同形)。 */\nexport type Translate = (\n\tkey: LocaleKey,\n\tparams?: Record<string, string | number>,\n) => string;\n\n/** 把宿主给的无参 t 包成带占位符替换的 t(模板一律 `{name}`,不依赖宿主是否支持 params)。 */\nexport function interpolateTranslate(base: Translate): Translate {\n\treturn (key, params) => {\n\t\tconst raw = base(key);\n\t\tif (params === undefined) return raw;\n\t\treturn raw.replace(/\\{(\\w+)\\}/g, (match, name: string) =>\n\t\t\tname in params ? String(params[name]) : match,\n\t\t);\n\t};\n}\n\n/** 键名兜底:宿主没给 t 席位时用(键名绝不上界面)。 */\nexport function fallbackTranslate(\n\tkey: LocaleKey,\n\tparams?: Record<string, string | number>,\n): string {\n\treturn interpolateTranslate((name) => zh[name] ?? name)(key, params);\n}\n","/**\n * 浏览器半入口(client bundle,产物 dist/client.js):装配层,不写业务逻辑。\n *\n * 三处注册各自挂进「服务就位才触发」的 slots 注入(参考插件真机教训:顶层 inject 声明\n * 组合满足不了的依赖会让 entry 一直 pending、卡死整个 dsh 启动):\n * · locale 字典(zh / en)——界面语言跟随宿主,插件不自备开关;\n * · `main` keyed 槽整页(看板首页)。\n *\n * 宿主能力一律**本地结构化声明**,不 import 官方包(rc 接口会无声变);\n * `t` 席位由宿主渲染器按注册项的 `locale:` 声明合成进组件 props。\n */\nimport { createElement as h } from \"react\";\nimport { BoardHome } from \"./board-home\";\nimport {\n\ten,\n\tfallbackTranslate,\n\tinterpolateTranslate,\n\ttype LocaleKey,\n\ttype Translate,\n\tzh,\n} from \"./locales\";\nimport { LedgerIcon } from \"./ui\";\n\n/** 命名空间(settings / locale / 面板 id 同名,便于对应)。 */\n/** 模块级 t 席位(侧栏 label 渲染期求值用;绑不上就回落键名,绝不上界面)。 */\nlet runtimeT: Translate = (key) => key;\n\nconst NS = \"dsh-task-ledger\";\n/** `main` 槽的 key(非 `conversation` ⇒ 不绑 Session)。 */\nconst PANEL_ID = NS;\n\n/** 浏览器插件上下文:只声明本文件实际用到的服务面。 */\ninterface ClientContext {\n\tinject(deps: readonly string[], callback: (ctx: ClientContext) => void): void;\n\teffect(setup: () => void): void;\n\tlocale?: {\n\t\tregister(\n\t\t\tns: string,\n\t\t\tdictionaries: Record<string, Record<string, string>>,\n\t\t): void;\n\t\t/** 绑一份无参 t(侧栏 label 在渲染期求值,拿不到组件 props 的 t 席位)。 */\n\t\tbind(ns: string): Translate;\n\t};\n\tlayout?: {\n\t\tselectPanel(panelId: string | null): void;\n\t};\n\tslots: {\n\t\tinject(slot: string, factory: () => () => void): () => void;\n\t\tregister(options: Record<string, unknown>, component: unknown): () => void;\n\t};\n}\n\n/** 宿主没给 t 席位时的兜底(键名绝不上界面)。 */\nconst t: Translate = interpolateTranslate(\n\t(key: LocaleKey, params?: Record<string, string | number>) =>\n\t\tfallbackTranslate(key, params),\n);\n\nexport function apply(ctx: ClientContext): void {\n\t// ① 字典注册(宿主语言切换 ⇒ 渲染器换 t 引用 ⇒ 整页重渲染)\n\tctx.inject([\"locale\"], (localeCtx) => {\n\t\tctx.effect(() => localeCtx.locale?.register(NS, { zh, en }));\n\t\t// 模块级 t 席位:`sidebar.panellist` 的 label 由侧栏在渲染期求值,拿不到组件 props 的 t\n\t\ttry {\n\t\t\truntimeT = localeCtx.locale?.bind(NS) ?? runtimeT;\n\t\t} catch {\n\t\t\t/* 保持键名兜底 */\n\t\t}\n\t});\n\n\t// ② 布局服务:浮标点开整页 / 整页返回会话\n\tlet selectPanel: (id: string | null) => void = () => {};\n\tctx.inject([\"layout\"], (sub) => {\n\t\tconst layout = sub.layout;\n\t\tif (layout !== undefined)\n\t\t\tselectPanel = (id) => {\n\t\t\t\tlayout.selectPanel(id);\n\t\t\t};\n\t});\n\n\t// ③ 槽位注册(只依赖 slots,自成一块:locale / layout 缺席也不该让入口消失)\n\tctx.inject([\"slots\"], (sub) => {\n\t\t// 左侧入口:侧栏面板条目(list 槽)。**行按钮、点击、激活态全由侧栏 / 布局服务托管**,\n\t\t// 组件只画图标;id 必须与 main 槽的 key 一致(同一 MainPanelId)。\n\t\t// 事实见 external/client-ui-layout.md §一/§二(0.2.0-rc.2 亲验)。\n\t\tsub.slots.inject(\"sidebar.panellist\", () =>\n\t\t\tsub.slots.register(\n\t\t\t\t{\n\t\t\t\t\tname: \"sidebar.panellist\",\n\t\t\t\t\tid: PANEL_ID,\n\t\t\t\t\torder: 30,\n\t\t\t\t\tlabel: () => runtimeT(\"panelTitle\"),\n\t\t\t\t\tlocale: NS,\n\t\t\t\t},\n\t\t\t\t(props: { size?: number }) => h(LedgerIcon, { size: props.size ?? 18 }),\n\t\t\t),\n\t\t);\n\t\tsub.slots.inject(\"main\", () =>\n\t\t\tsub.slots.register(\n\t\t\t\t{ name: \"main\", key: PANEL_ID, locale: NS },\n\t\t\t\t(props: { t?: Translate }) =>\n\t\t\t\t\th(BoardHome, {\n\t\t\t\t\t\tt: props.t ?? t,\n\t\t\t\t\t\tonBack: () => {\n\t\t\t\t\t\t\tselectPanel(null);\n\t\t\t\t\t\t},\n\t\t\t\t\t}),\n\t\t\t),\n\t\t);\n\t});\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"client.js","names":["current","getComputedStyle","index","useLayoutEffect","SafeReact","React","tabbable","computePosition","flip","offset","shift","size","offset","shift","flip","size","useLayoutEffect","React","useFloating","offset$1","shift$1","flip$1","size$1","React","t","h","t","size","useMemo","useState","useRef","floatingSize","useCallback","h","Button","h","IconButton","t","h","h","Segmented","useRef","useState","useCallback","h","h","h","CoreSegmented","CoreButton","CoreIconButton","CorePicker","CoreInput","CoreChip","Tooltip","useState","h","Tooltip","IconSearchOutlineRegular","IconDownloadOutlineRegular","IconChevronRightOutlineRegular","IconCheckOutlineRegular","useSyncExternalStore","useState","useMemo","h","IconRefreshOutlineRegular","IconChecklistOutlineRegular","IconFlatListOutlineRegular","IconFolderOpenRegular","IconFolderCloseRegular","h"],"sources":["../../../node_modules/.pnpm/dsh-plugin-core@0.5.0_@babel+runtime@8.0.8_@codemirror+autocomplete@6.20.4_@codemirror+_bddbf1bc7ba0e94be71f734653121d0c/node_modules/dsh-plugin-core/dist/design/tokens-css.generated.js","../../../node_modules/.pnpm/dsh-plugin-core@0.5.0_@babel+runtime@8.0.8_@codemirror+autocomplete@6.20.4_@codemirror+_bddbf1bc7ba0e94be71f734653121d0c/node_modules/dsh-plugin-core/dist/design/style-kit.js","../../../node_modules/.pnpm/dsh-plugin-core@0.5.0_@babel+runtime@8.0.8_@codemirror+autocomplete@6.20.4_@codemirror+_bddbf1bc7ba0e94be71f734653121d0c/node_modules/dsh-plugin-core/dist/ui/controls/segmented-css.generated.js","../../../node_modules/.pnpm/dsh-plugin-core@0.5.0_@babel+runtime@8.0.8_@codemirror+autocomplete@6.20.4_@codemirror+_bddbf1bc7ba0e94be71f734653121d0c/node_modules/dsh-plugin-core/dist/ui/controls/button-css.generated.js","../../../node_modules/.pnpm/dsh-plugin-core@0.5.0_@babel+runtime@8.0.8_@codemirror+autocomplete@6.20.4_@codemirror+_bddbf1bc7ba0e94be71f734653121d0c/node_modules/dsh-plugin-core/dist/ui/controls/field-css.generated.js","../../../node_modules/.pnpm/dsh-plugin-core@0.5.0_@babel+runtime@8.0.8_@codemirror+autocomplete@6.20.4_@codemirror+_bddbf1bc7ba0e94be71f734653121d0c/node_modules/dsh-plugin-core/dist/ui/controls/loading-css.generated.js","../../../node_modules/.pnpm/dsh-plugin-core@0.5.0_@babel+runtime@8.0.8_@codemirror+autocomplete@6.20.4_@codemirror+_bddbf1bc7ba0e94be71f734653121d0c/node_modules/dsh-plugin-core/dist/ui/controls/back-to-top-css.generated.js","../../../node_modules/.pnpm/dsh-plugin-core@0.5.0_@babel+runtime@8.0.8_@codemirror+autocomplete@6.20.4_@codemirror+_bddbf1bc7ba0e94be71f734653121d0c/node_modules/dsh-plugin-core/dist/ui/controls/hint-css.generated.js","../../../node_modules/.pnpm/dsh-plugin-core@0.5.0_@babel+runtime@8.0.8_@codemirror+autocomplete@6.20.4_@codemirror+_bddbf1bc7ba0e94be71f734653121d0c/node_modules/dsh-plugin-core/dist/ui/controls/datetime-css.generated.js","../../../node_modules/.pnpm/dsh-plugin-core@0.5.0_@babel+runtime@8.0.8_@codemirror+autocomplete@6.20.4_@codemirror+_bddbf1bc7ba0e94be71f734653121d0c/node_modules/dsh-plugin-core/dist/ui/marquee-css.generated.js","../../../node_modules/.pnpm/dsh-plugin-core@0.5.0_@babel+runtime@8.0.8_@codemirror+autocomplete@6.20.4_@codemirror+_bddbf1bc7ba0e94be71f734653121d0c/node_modules/dsh-plugin-core/dist/ui/picker-css.generated.js","../../../node_modules/.pnpm/dsh-plugin-core@0.5.0_@babel+runtime@8.0.8_@codemirror+autocomplete@6.20.4_@codemirror+_bddbf1bc7ba0e94be71f734653121d0c/node_modules/dsh-plugin-core/dist/ui/feedback-css.generated.js","../../../node_modules/.pnpm/dsh-plugin-core@0.5.0_@babel+runtime@8.0.8_@codemirror+autocomplete@6.20.4_@codemirror+_bddbf1bc7ba0e94be71f734653121d0c/node_modules/dsh-plugin-core/dist/ui/card-css.generated.js","../../../node_modules/.pnpm/dsh-plugin-core@0.5.0_@babel+runtime@8.0.8_@codemirror+autocomplete@6.20.4_@codemirror+_bddbf1bc7ba0e94be71f734653121d0c/node_modules/dsh-plugin-core/dist/ui/chip-css.generated.js","../../../node_modules/.pnpm/dsh-plugin-core@0.5.0_@babel+runtime@8.0.8_@codemirror+autocomplete@6.20.4_@codemirror+_bddbf1bc7ba0e94be71f734653121d0c/node_modules/dsh-plugin-core/dist/ui/code-viewer-css.generated.js","../../../node_modules/.pnpm/dsh-plugin-core@0.5.0_@babel+runtime@8.0.8_@codemirror+autocomplete@6.20.4_@codemirror+_bddbf1bc7ba0e94be71f734653121d0c/node_modules/dsh-plugin-core/dist/ui/panel-dock-css.generated.js","../../../node_modules/.pnpm/dsh-plugin-core@0.5.0_@babel+runtime@8.0.8_@codemirror+autocomplete@6.20.4_@codemirror+_bddbf1bc7ba0e94be71f734653121d0c/node_modules/dsh-plugin-core/dist/explorer/explorer-css.generated.js","../../../node_modules/.pnpm/dsh-plugin-core@0.5.0_@babel+runtime@8.0.8_@codemirror+autocomplete@6.20.4_@codemirror+_bddbf1bc7ba0e94be71f734653121d0c/node_modules/dsh-plugin-core/dist/session/session-css.generated.js","../../../node_modules/.pnpm/dsh-plugin-core@0.5.0_@babel+runtime@8.0.8_@codemirror+autocomplete@6.20.4_@codemirror+_bddbf1bc7ba0e94be71f734653121d0c/node_modules/dsh-plugin-core/dist/ui/css.js","../../../node_modules/.pnpm/dsh-plugin-core@0.5.0_@babel+runtime@8.0.8_@codemirror+autocomplete@6.20.4_@codemirror+_bddbf1bc7ba0e94be71f734653121d0c/node_modules/dsh-plugin-core/dist/ui/picker-logic.js","../../../node_modules/.pnpm/@floating-ui+utils@0.2.12/node_modules/@floating-ui/utils/dist/floating-ui.utils.dom.mjs","../../../node_modules/.pnpm/@floating-ui+utils@0.2.12/node_modules/@floating-ui/utils/dist/floating-ui.utils.mjs","../../../node_modules/.pnpm/tabbable@6.5.1/node_modules/tabbable/dist/index.js","../../../node_modules/.pnpm/@floating-ui+react@0.27.20_react-dom@19.3.1_react@19.3.1__react@19.3.1/node_modules/@floating-ui/react/dist/floating-ui.react.utils.mjs","../../../node_modules/.pnpm/@floating-ui+core@1.8.0/node_modules/@floating-ui/core/dist/floating-ui.core.mjs","../../../node_modules/.pnpm/@floating-ui+dom@1.8.0/node_modules/@floating-ui/dom/dist/floating-ui.dom.mjs","../../../node_modules/.pnpm/@floating-ui+react-dom@2.1.9_react-dom@19.3.1_react@19.3.1__react@19.3.1/node_modules/@floating-ui/react-dom/dist/floating-ui.react-dom.mjs","../../../node_modules/.pnpm/@floating-ui+react@0.27.20_react-dom@19.3.1_react@19.3.1__react@19.3.1/node_modules/@floating-ui/react/dist/floating-ui.react.mjs","../../../node_modules/.pnpm/dsh-plugin-core@0.5.0_@babel+runtime@8.0.8_@codemirror+autocomplete@6.20.4_@codemirror+_bddbf1bc7ba0e94be71f734653121d0c/node_modules/dsh-plugin-core/dist/utils/i18n.js","../../../node_modules/.pnpm/dsh-plugin-core@0.5.0_@babel+runtime@8.0.8_@codemirror+autocomplete@6.20.4_@codemirror+_bddbf1bc7ba0e94be71f734653121d0c/node_modules/dsh-plugin-core/dist/ui/tooltip.js","../../../node_modules/.pnpm/dsh-plugin-core@0.5.0_@babel+runtime@8.0.8_@codemirror+autocomplete@6.20.4_@codemirror+_bddbf1bc7ba0e94be71f734653121d0c/node_modules/dsh-plugin-core/dist/ui/FieldHint.js","../../../node_modules/.pnpm/dsh-plugin-core@0.5.0_@babel+runtime@8.0.8_@codemirror+autocomplete@6.20.4_@codemirror+_bddbf1bc7ba0e94be71f734653121d0c/node_modules/dsh-plugin-core/dist/ui/Picker.js","../../../node_modules/.pnpm/dsh-plugin-core@0.5.0_@babel+runtime@8.0.8_@codemirror+autocomplete@6.20.4_@codemirror+_bddbf1bc7ba0e94be71f734653121d0c/node_modules/dsh-plugin-core/dist/ui/Button.js","../../../node_modules/.pnpm/dsh-plugin-core@0.5.0_@babel+runtime@8.0.8_@codemirror+autocomplete@6.20.4_@codemirror+_bddbf1bc7ba0e94be71f734653121d0c/node_modules/dsh-plugin-core/dist/ui/Card.js","../../../node_modules/.pnpm/dsh-plugin-core@0.5.0_@babel+runtime@8.0.8_@codemirror+autocomplete@6.20.4_@codemirror+_bddbf1bc7ba0e94be71f734653121d0c/node_modules/dsh-plugin-core/dist/ui/Chip.js","../../../node_modules/.pnpm/dsh-plugin-core@0.5.0_@babel+runtime@8.0.8_@codemirror+autocomplete@6.20.4_@codemirror+_bddbf1bc7ba0e94be71f734653121d0c/node_modules/dsh-plugin-core/dist/ui/Segmented.js","../../../node_modules/.pnpm/dsh-plugin-core@0.5.0_@babel+runtime@8.0.8_@codemirror+autocomplete@6.20.4_@codemirror+_bddbf1bc7ba0e94be71f734653121d0c/node_modules/dsh-plugin-core/dist/ui/Field.js","../src/client/rows.ts","../src/client/api.ts","../src/client/store.ts","../src/client/format.ts","../src/client/tokens.ts","../src/client/ui.ts","../src/client/task-row.ts","../src/client/board-home.ts","../src/client/locales.ts","../src/client/index.ts"],"sourcesContent":["// ⚠️ 生成物,勿手改。真源 = src/design/tokens.css\n// 由 scripts/gen-css.mjs 生成(`pnpm run gen:css`):改样式请改那个 .css 文件后重新生成。\nexport const TOKENS_CSS_TEMPLATE = \"\\n/* ── 文字(宿主 label 四档 + 反色面用字)────────────────────────────── */\\nbody{\\n --dshpc-fg:var(--dsw-alias-label-primary,#1f2328);\\n --dshpc-fg-2:var(--dsw-alias-label-secondary,#5c6370);\\n --dshpc-fg-3:var(--dsw-alias-label-tertiary,#767d87);\\n --dshpc-fg-4:var(--dsw-alias-label-caption,#9aa1ab);\\n --dshpc-fg-dim:var(--dsw-alias-label-dimmed,#b9bfc7);\\n /* 反色面上的字(实心钮 / 角标):暗色下是 bluish-1000,故用 -foreground 而非 -inverted */\\n --dshpc-fg-inverse:var(--dsw-alias-label-primary-foreground,#fff);\\n\\n /* ── 面(宿主 bg-layer 三档 + 下沉轨道底)──────────────────────────── */\\n --dshpc-surface-1:var(--dsw-alias-bg-layer-1,#fff);\\n --dshpc-surface-2:var(--dsw-alias-bg-layer-2,#fff);\\n --dshpc-surface-3:var(--dsw-alias-bg-layer-3,#fff);\\n /* 「选中亮片」的底盘色(配 --dshpc-shadow-raised 用) */\\n --dshpc-surface-raised:var(--dsw-alias-bg-layer-1,#fff);\\n /* 轨道 / 下沉底(官方分段控件轨道用的就是这条) */\\n --dshpc-surface-sunken:var(--dsw-alias-interactive-bg-hover,rgba(38,49,72,.06));\\n /* 整页 / 编辑器底(bg-base) */\\n --dshpc-surface-base:var(--dsw-alias-bg-base,#fff);\\n /* 自绘浮层 / 菜单卡的不透明底(= base;不要用半透明的 specific-menu) */\\n --dshpc-surface-menu:var(--dshpc-surface-base);\\n /* markdown 代码块面 / 字体(会话镜像里用到) */\\n --dshpc-code-surface:var(--dsw-alias-markdown-code-block,rgba(128,128,128,.10));\\n --dshpc-code-font:var(--dsw-font-markdown-code-block-small,12px/18px var(--ds-font-family-code,monospace));\\n /* 警告文字色(宿主 state-warn-label) */\\n --dshpc-warning-label:var(--dsw-alias-state-warn-label,#f5a623);\\n /* 固定中性实面(自绘浮层、深色主题下必须自己变的那几个)——只有它需要暗色覆盖 */\\n --dshpc-solid:var(--dsw-static-neutral-00,#fff);\\n --dshpc-on-solid:var(--dsw-alias-label-primary,#1f2328);\\n /* 交付文件卡那种「浅底盘 + hover 加深」两拍 */\\n --dshpc-plate:var(--dsw-static-neutral-50,#fafafa);\\n --dshpc-plate-hover:var(--dsw-static-neutral-100,#f5f5f5);\\n /* ⚠️ 这些**固定中性面一律用 rgba 字面量**(2026-10-19 真机教训):不要写成\\n 「rgba 回退行 + 嵌 --dsw-static-* 的 color-mix 行」两条同名声明——自定义属性**后者恒胜**,\\n 哪怕它的值在宿主里算不出来(static 变量 invalid)⇒ 整条 token 作废、rgba 兜底一起被废,\\n 0.2.6 里 Segmented 轨道全透明就是这么来的。要跟宿主主题联动的面用 alias token(那些实测有效)。 */\\n --dshpc-icon-plate:rgba(255,255,255,.5);\\n /* 表头底:浅色主题**偏深**,且必须**比斑马纹(--dshpc-plate)再深一档**——\\n 两者不能撞色(用户 2026-10-02:表头跟斑马纹一模一样)。 */\\n --dshpc-head-bg:var(--dsw-static-neutral-100,#f5f5f5);\\n /* 图标小底板(产出物):浅色下要**看得见**(原先取 plate ⇒ 在白底上等于没有);hover 加倍。 */\\n --dshpc-chip-bg:rgba(15,15,15,.07);\\n --dshpc-chip-bg-hover:rgba(15,15,15,.14);\\n /* 展开行:**带透明度的蓝**——不是灰、也不是纯色,透出卡片底色,一眼看出「这是展开的」\\n (用户 2026-10-02:灰色跟斑马纹分不出来)。内容区再淡一档,形成「行深 / 内容浅」的区隔。 */\\n --dshpc-open-bg:rgba(37,99,235,.10);\\n --dshpc-open-bg-soft:rgba(37,99,235,.05);\\n --dshpc-card-hover:rgba(37,99,235,.07);\\n\\n /* ── 描边四档(宿主真值:l1 4% / l2 10% / l3 12% / l4 16%)────────── */\\n --dshpc-border-faint:var(--dsw-alias-border-l1,#0000000a);\\n --dshpc-border:var(--dsw-alias-border-l2,#0000001a);\\n --dshpc-border-strong:var(--dsw-alias-border-l3,#0000001f);\\n --dshpc-border-heavy:var(--dsw-alias-border-l4,#00000029);\\n\\n /* ── 品牌 / 语义色 ────────────────────────────────────────────────── */\\n /* 品牌「面」色:明色近黑、暗色近白(官方 Switch 选中态即此),**不是蓝色** */\\n --dshpc-accent:var(--dsw-alias-brand-primary,#0f1115);\\n /* 蓝色:强调 / 选中 / 焦点,一律走这条 */\\n --dshpc-business:var(--dsw-alias-state-business-primary,#3b5bdb);\\n --dshpc-success:var(--dsw-alias-state-success-primary,#22c55e);\\n /* ⚠️ 是 state-warn(不是 state-warning,后者宿主无此定义) */\\n --dshpc-warning:var(--dsw-alias-state-warn-primary,#f59e0b);\\n --dshpc-danger:var(--dsw-alias-state-error-primary,#ec1313);\\n --dshpc-link:var(--dsw-alias-link,#3b5bdb);\\n /* 语义色**实面**上的字(角标 / 实心提示):宿主红绿黄三色都是中调 ⇒ 白字两个主题都可读,\\n 故这是一条与主题无关的常量;不要拿 --dshpc-fg-inverse 顶——它在暗色下是近黑,压在红底上看不清。 */\\n --dshpc-on-signal:#fff;\\n /* 黄底上的字:黄色是中高明度,白字看不清 ⇒ 固定深色(与主题无关)。 */\\n --dshpc-on-warning:#1f2328;\\n\\n /* ── 实心按钮的 hover / active 派生态(2026-10-19 用户点名)─────────────────\\n 原实现是 :hover 直接压 opacity .9:黑底压 10% 几乎看不出来,用户原话「完全感觉不到颜色变了」。\\n ⇒ 改成对底色做**明确的混色**(压 22% / 34%),不用 opacity:\\n · 亮色主题:黑底(--dshpc-accent)掺白提亮;红 / 绿 / 黄 / 蓝底掺黑压深;\\n · 暗色主题:反过来(暗底掺白、亮底掺黑)。\\n 混色对象是**固定中性色字面量**(#fff / #000),不依赖宿主 static-neutral 是否存在;\\n 旧内核不认 color-mix 时整条声明作废 ⇒ 回落各档原色(可接受:仍可点,只是没有 hover 反馈)。 */\\n --dshpc-accent-hover:color-mix(in srgb,var(--dshpc-accent) 78%,#ffffff);\\n --dshpc-accent-active:color-mix(in srgb,var(--dshpc-accent) 64%,#ffffff);\\n --dshpc-danger-hover:color-mix(in srgb,var(--dshpc-danger) 78%,#000000);\\n --dshpc-danger-active:color-mix(in srgb,var(--dshpc-danger) 64%,#000000);\\n --dshpc-success-hover:color-mix(in srgb,var(--dshpc-success) 78%,#000000);\\n --dshpc-success-active:color-mix(in srgb,var(--dshpc-success) 64%,#000000);\\n --dshpc-warning-hover:color-mix(in srgb,var(--dshpc-warning) 78%,#000000);\\n --dshpc-warning-active:color-mix(in srgb,var(--dshpc-warning) 64%,#000000);\\n --dshpc-business-hover:color-mix(in srgb,var(--dshpc-business) 78%,#000000);\\n --dshpc-business-active:color-mix(in srgb,var(--dshpc-business) 64%,#000000);\\n /* 语义色**浅底**:状态色系的「一块底色」——执行记录页每条流水账的块底就是它\\n (用户 2026-10-04:正常态给同色系很浅的透明底、失败用红底透出来)。\\n 用 「color-mix」 现算而不写死 rgba:状态色本身跟随宿主 alias,主题一换自动成立。\\n ⚠️ **深色下要更淡**:用户 2026-10-04「深色风格的绿色和红色好像都有点深」⇒ dark 段\\n 把这四条压到 5%(更贴近面板底、存在感更弱);浅色段维持 8%。两端各自给值,不共用一条曲线。\\n 命名收在 tokens.ts 单点(本仓硬规矩:业务文件不许自造 --dshpc-*)。 */\\n --dshpc-success-soft:color-mix(in srgb,var(--dshpc-success) 8%,transparent);\\n --dshpc-warning-soft:color-mix(in srgb,var(--dshpc-warning) 8%,transparent);\\n --dshpc-danger-soft:color-mix(in srgb,var(--dshpc-danger) 8%,transparent);\\n --dshpc-business-soft:color-mix(in srgb,var(--dshpc-business) 8%,transparent);\\n\\n /* ⚠️ 2026-10-18 用户拍板:宿主 alias 的 hover(暗色白 8% / 亮色 6%)**太弱**,\\n 「移上去要仔细看才看得出来」⇒ 不再委托宿主 hover 别名,改为自掺中性色并加重:\\n 亮色掺黑 10%、暗色掺白 14%(active 再加一档)。按钮 / 分段轨道 / 各类 hover 底同时受益。\\n ⚠️ 必须保留 rgba 兜底行在前(本文件惯例,见 icon-plate 注释):掺的是**固定中性色**\\n (neutral-900=#0f0f0f / neutral-00=#fff),预计算无损;旧内核不认 color-mix 时走兜底,\\n 否则整条 background:var(--seg-track) 作废 ⇒ 分段轨道透明(真踩过:预览站轨道消失)。 */\\n --dshpc-hover:rgba(15,15,15,.10);\\n --dshpc-active:rgba(15,15,15,.18);\\n /* 分段控件轨道底:专用 token(rgba 字面量、不借 --dshpc-hover 中转)——\\n 2026-10-19 教训:变量链中间任何一环 invalid ⇒ background 整条作废、轨道全透明。\\n 亮色:黑 7%(比 hover 的 10% 淡一档,选中白片才跳得出)。 */\\n --dshpc-seg-track:rgba(15,15,15,.07);\\n --dshpc-mask:var(--dsw-alias-bg-mask-1,#0000003d);\\n /* 「选中面」(2026-10-06,任务日程页首创)= 当前底色**朝更深掺 12% 文字色**:\\n 浅色主题下文字色是黑 ⇒ 选中面比常态底色**深一档**。深色分支见 body[data-ds-dark-theme](朝背景色掺)。\\n 语义:标记「正在看的东西」,比常态明显、又不许盖住内容(不许用半透明叠状态色)。 */\\n --dshpc-selected-bg:color-mix(in srgb,var(--dshpc-surface-1) 88%,var(--dshpc-fg));\\n /* 任务日程页本月格默认底(2026-10-06 → 续2):浅色下给**淡蓝**(business 8% 透白底)——\\n 参照用户参考稿里未选中日程块 / Tuesday 列的那种蓝、再浅一点点;\\n 相邻月补位格仍走 --dshpc-surface-2(更灰),不受影响。\\n 深色段维持 #23262e(用户:深色 UI 已差不多,不动)。 */\\n --dshpc-cal-cell-bg:color-mix(in srgb,var(--dshpc-business) 8%,var(--dshpc-surface-1));\\n /* 任务日程页「点开某天」展开的面板底(2026-10-06 续):浅色下**无限接近白、只带一丁点灰**\\n (neutral-50 = #fafafa)——面板里装半透明执行记录列表,底再深整片就发糊发灰;\\n 深色段沿用原 selected-bg 暗值,保持不动。 */\\n --dshpc-cal-panel-bg:var(--dsw-static-neutral-50,#fafafa);\\n /* 任务日程页本月格 hover 底(浅色段,2026-10-06 续3):不再走灰色通用交互底——\\n 鼠标移上去应是「更亮一点点的蓝」(与深色段同语义:hover = 提亮的蓝,不是灰下去)。\\n 浓度**介于**表头蓝(14%)与未选中格蓝(8%)之间、略偏表头一侧:business 12% 透白底\\n (比表头浅一点、比未选中格深一点)。 */\\n --dshpc-cal-cell-hover:color-mix(in srgb,var(--dshpc-business) 12%,var(--dshpc-surface-1));\\n\\n /* ── 投影 / 焦点 ──────────────────────────────────────────────────── */\\n --dshpc-shadow-1:var(--dsw-elevation-soft,0 4px 16px 0 #00000008);\\n /* 亮片自带的浮起感(选中态用;与 --dshpc-surface-raised 配对) */\\n --dshpc-shadow-raised:var(--dsw-elevation-soft,0 4px 16px 0 #00000008);\\n --dshpc-shadow-2:var(--dsw-shadow-lv3,0 12px 32px 0 #00000014);\\n /* 键盘焦点环。⚠️ 不用宿主 --dsw-focus-ring-color:它默认值是 transparent(兜底不生效、会隐身) */\\n --dshpc-focus:var(--dsw-alias-state-business-primary,#3b5bdb);\\n\\n /* ── 圆角(宿主真值 4 / 8 / 12 / 16 / 20 / 28)─────────────────────── */\\n --dshpc-radius-xs:var(--dsw-radius-xs,4px);\\n --dshpc-radius-sm:var(--dsw-radius-sm,8px);\\n --dshpc-radius-md:var(--dsw-radius-md,12px);\\n --dshpc-radius-lg:var(--dsw-radius-lg,16px);\\n --dshpc-radius-xl:var(--dsw-radius-xl,20px);\\n --dshpc-radius-panel:var(--dsw-radius-panel,28px);\\n /* 全圆(胶囊标签):宿主的 radius 档最大只有 28px,撑不满 24px 高的 chip */\\n --dshpc-radius-pill:999px;\\n\\n /* ── 间距四拍(只许用这四档,不许出现 5 / 7 / 9px)────────────────── */\\n --dshpc-space-1:4px;\\n --dshpc-space-2:8px;\\n --dshpc-space-3:12px;\\n --dshpc-space-4:16px;\\n\\n /* ── 控件高度:离散三档(控件用 size=\\\"sm|md|lg\\\" 选;调用点不许自定义高度,\\n 真不够用才允许在调用点本地覆盖 --dshpc-control-h-*,属例外而非常态)── */\\n --dshpc-control-h-sm:24px;\\n --dshpc-control-h-md:28px;\\n --dshpc-control-h-lg:32px;\\n\\n /* ── 字号 / 行高:直绑宿主字号族(宿主真值 11 / 12 / 13 / 14 / 16)───── */\\n --dshpc-font-xs:var(--dsw-font-xxxs-11-font-size,11px);\\n --dshpc-font-sm:var(--dsw-font-xxs-12-font-size,12px);\\n --dshpc-font-md:var(--dsw-font-xs-13-font-size,13px);\\n --dshpc-font-lg:var(--dsw-font-s-14-font-size,14px);\\n --dshpc-font-xl:var(--dsw-font-base-16-font-size,16px);\\n --dshpc-line-xs:var(--dsw-font-xxxs-11-line-height,14px);\\n --dshpc-line-sm:var(--dsw-font-xxs-12-line-height,18px);\\n --dshpc-line-md:var(--dsw-font-xs-13-line-height,20px);\\n --dshpc-line-lg:var(--dsw-font-s-14-line-height,22px);\\n --dshpc-line-xl:var(--dsw-font-base-16-line-height,24px);\\n --dshpc-font-mono:var(--ds-font-family-code,monospace);\\n\\n /* ── 层级阶梯(业务文件不许再写裸 z-index)───────────────────────── */\\n /* 页面级预览分栏 → 抽屉(新建/编辑)→ 弹窗/确认框 → 浮层菜单 → 浮层提示 */\\n /* 内容层吸顶(天标签 / 表头这类「跟着滚但压住同层内容」的元素):只压同层兄弟,\\n 必须低于下面所有浮层档 —— 所以它不是「开新浮层档」,而是内容层内部的排序位。 */\\n --dshpc-z-sticky:10;\\n --dshpc-z-dock:1030;\\n --dshpc-z-drawer:1040;\\n --dshpc-z-modal:1070;\\n --dshpc-z-menu:1100;\\n --dshpc-z-tip:1200;\\n\\n /* ── 动效 ─────────────────────────────────────────────────────────── */\\n --dshpc-dur:var(--ds-transition-duration,.2s);\\n --dshpc-dur-fast:var(--ds-transition-duration-fast,.12s);\\n --dshpc-ease:var(--ds-ease-in-out,cubic-bezier(.4,0,.2,1));\\n /* 运行中状态的脉动时长(2026-10-06 统一前后两端:任务配置里的绿呼吸 → 蓝、放慢;\\n 执行记录里的蓝闪 → 放慢一点。两者用同一个值,动画形状本就一致)。 */\\n --dshpc-dur-run:500ms;\\n}\\n\\n/* ── 明暗差异的**唯一**落点 ──────────────────────────────────────────────\\n 判据 = body[data-ds-dark-theme](宿主 0.2.0-rc.2 源码核实:启动脚本 toggleAttribute 写入,\\n 唯一明暗判据;插件禁止用 prefers-color-scheme —— 它跟的是系统、不是用户在宿主里的选择)。\\n 下面只放 alias 表达不了的「固定中性面」;颜色若能靠 alias 自动跟随,一律不要写在这里。 */\\nbody[data-ds-dark-theme]{\\n --dshpc-solid:var(--dsw-static-neutral-900,#0f0f0f);\\n --dshpc-on-solid:var(--dsw-static-neutral-00,#fff);\\n /* 实心按钮 hover / active(暗色版):黑底(浅色主题的近黑 → 暗色下的近白)掺黑压深;\\n 红 / 绿 / 黄 / 蓝掺白提亮。与亮色段方向相反,保证两种主题下「一眼看出变了」。 */\\n --dshpc-accent-hover:color-mix(in srgb,var(--dshpc-accent) 80%,#000000);\\n --dshpc-accent-active:color-mix(in srgb,var(--dshpc-accent) 66%,#000000);\\n --dshpc-danger-hover:color-mix(in srgb,var(--dshpc-danger) 78%,#ffffff);\\n --dshpc-danger-active:color-mix(in srgb,var(--dshpc-danger) 64%,#ffffff);\\n --dshpc-success-hover:color-mix(in srgb,var(--dshpc-success) 78%,#ffffff);\\n --dshpc-success-active:color-mix(in srgb,var(--dshpc-success) 64%,#ffffff);\\n --dshpc-warning-hover:color-mix(in srgb,var(--dshpc-warning) 78%,#ffffff);\\n --dshpc-warning-active:color-mix(in srgb,var(--dshpc-warning) 64%,#ffffff);\\n --dshpc-business-hover:color-mix(in srgb,var(--dshpc-business) 78%,#ffffff);\\n --dshpc-business-active:color-mix(in srgb,var(--dshpc-business) 64%,#ffffff);\\n /* 暗色 hover 掺白 14% / active 24%(对齐上面 2026-10-18 的加重拍板)。rgba 兜底行同上。 */\\n --dshpc-hover:rgba(255,255,255,.14);\\n --dshpc-active:rgba(255,255,255,.24);\\n /* 分段轨道(暗色版):白 10%——比 hover 淡一档,选中亮片才跳得出。 */\\n --dshpc-seg-track:rgba(255,255,255,.10);\\n --dshpc-plate:var(--dsw-static-neutral-850,#212123);\\n --dshpc-plate-hover:var(--dsw-static-neutral-800,#292929);\\n --dshpc-icon-plate:rgba(255,255,255,.05);\\n /* 暗色主题**反过来**:表头要比卡片面**亮**、比斑马纹再**浅一档**(用户:纯黑背景没法看)。 */\\n --dshpc-head-bg:var(--dshpc-surface-2);\\n /* 暗色底板**微亮**;hover **更亮**(原先 hover 取 plate-hover 反而更淡 ⇒ 鼠标移上去就没了)。 */\\n --dshpc-chip-bg:rgba(255,255,255,.08);\\n --dshpc-chip-bg-hover:rgba(255,255,255,.16);\\n /* 暗色下蓝色要更亮、透明度略高才压得住深底。 */\\n --dshpc-open-bg:rgba(96,165,250,.18);\\n --dshpc-open-bg-soft:rgba(96,165,250,.08);\\n --dshpc-card-hover:rgba(96,165,250,.13);\\n /* 语义色**浅底**(深色版):用户嫌深色的绿 / 红「有点深」⇒ 压到 **5%**(浅色段是 8%),\\n 更贴近面板底色、存在感更弱;块底与状态色竖条仍同源(竖条是实色,不受这条影响)。 */\\n --dshpc-success-soft:color-mix(in srgb,var(--dshpc-success) 5%,transparent);\\n --dshpc-warning-soft:color-mix(in srgb,var(--dshpc-warning) 5%,transparent);\\n --dshpc-danger-soft:color-mix(in srgb,var(--dshpc-danger) 5%,transparent);\\n --dshpc-business-soft:color-mix(in srgb,var(--dshpc-business) 5%,transparent);\\n /* 「选中面」(深色版,2026-10-06):掺 **~40% 背景色**(--dshpc-surface-base)⇒ 无限接近页面背景的黑、\\n 只比背景略深一点点(用户:深色下展开区压着任务透明绿会发灰,底色要尽量贴近背景才不显灰)。\\n ⚠️ 深色下不能掺文字色 —— 那是白,会变亮,选中反而比本月日期浅。 */\\n --dshpc-selected-bg:color-mix(in srgb,var(--dshpc-surface-1) 60%,var(--dshpc-surface-base));\\n /* 任务日程页本月格的默认底(深色版,2026-10-06):深的、带点灰蓝的暗色(用户给的参考图 ≈ #23262e),\\n 比原来的卡片面更沉、更偏蓝灰;选中格仍走 --dshpc-selected-bg(更暗一档),层级不变。 */\\n --dshpc-cal-cell-bg:#23262e;\\n /* 任务日程页本月格 hover 底(深色段,2026-10-06):原先走 --dshpc-hover(宿主浅色叠加)在深底上显得\\n 「灰发亮」,不好看 ⇒ 换成更贴底的蓝调微亮(与 open-bg-soft 同族),hover 时不刺眼、又有反馈。 */\\n --dshpc-cal-cell-hover:rgba(96,165,250,.12);\\n /* 任务日程页展开面板底(深色段,2026-10-06 续):与原 selected-bg 暗值一致,深色 UI 不动 */\\n --dshpc-cal-panel-bg:color-mix(in srgb,var(--dshpc-surface-1) 60%,var(--dshpc-surface-base));\\n}\\n\";\n//# sourceMappingURL=tokens-css.generated.js.map","import { TOKENS_CSS_TEMPLATE } from './tokens-css.js';\n/** 明暗判据(宿主启动脚本 `toggleAttribute` 写入 body,是用户在客户端里的选择)。 */\nexport const DARK_THEME_SELECTOR = 'body[data-ds-dark-theme]';\n/** 全生态统一的 CSS 变量前缀。 */\nconst CSS_PREFIX = 'dshpc';\n/** token 域固定名:变量定义必须先于消费它的规则出现。 */\nconst TOKENS_DOMAIN = 'tokens';\n/**\n * 领一套本插件专属的样式设施。\n *\n * 为什么是工厂而不是模块级单例:单例只有一个固定 style id,\n * 多个插件同处一页时会抢同一个 `<style>` 标签、后挂载的覆盖先挂载的(见需求文档 §5.2)。\n */\nexport function createStyleKit(options) {\n const { id } = options;\n if (id === '')\n throw new Error('dsh-plugin-core/design: id 不能为空');\n const tokensCss = TOKENS_CSS_TEMPLATE;\n const domains = new Map();\n let tag = null;\n let dirty = true;\n const composeCss = () => {\n const entries = [...domains.entries()];\n entries.sort((a, b) => (a[0] === TOKENS_DOMAIN ? -1 : b[0] === TOKENS_DOMAIN ? 1 : 0));\n return entries.map(([, css]) => css).join('\\n');\n };\n const flush = () => {\n if (tag === null)\n return;\n tag.textContent = composeCss();\n dirty = false;\n };\n const ensureStyles = () => {\n if (typeof document === 'undefined')\n return;\n if (tag === null || !tag.isConnected) {\n const head = document.head;\n if (head === null)\n return;\n const found = document.getElementById(id);\n if (found !== null)\n tag = found;\n else {\n const el = document.createElement('style');\n el.id = id;\n head.appendChild(el);\n tag = el;\n }\n dirty = true;\n }\n if (dirty)\n flush();\n };\n const registerStyle = (domain, css) => {\n if (domains.get(domain) === css)\n return;\n domains.set(domain, css);\n dirty = true;\n if (tag?.isConnected === true)\n flush();\n };\n const dispose = () => {\n if (tag?.isConnected === true)\n tag.remove();\n tag = null;\n domains.clear();\n dirty = true;\n };\n return {\n id,\n tokensCss,\n cssVar: (name) => `--${CSS_PREFIX}-${name}`,\n registerStyle,\n ensureStyles,\n dispose,\n applyStyle: (domain, css) => {\n registerStyle(domain, css);\n ensureStyles();\n },\n };\n}\n//# sourceMappingURL=style-kit.js.map","// ⚠️ 生成物,勿手改。真源 = src/ui/controls/segmented.css\n// 由 scripts/gen-css.mjs 生成(`pnpm run gen:css`):改样式请改那个 .css 文件后重新生成。\nexport const SEGMENTED_CSS = \"\\n/* ── 分段控件 P2 ─────────────────────────────────────────────────────\\n 结构照兄弟项目 dsh-task-dispatch-table 的 Segmented 皮肤(item 无边框、hover 只提亮文字),\\n 前缀 / 变量名换成本仓口径。用户额外要的两处(兄弟没有):weekday 方块间隔(现为 2px);段内中性计数 __count。\\n ⚠️ 2026-10-19 两次误判均已澄清:① 「宿主只认单行 CSS」——假,多行一直正常;\\n ② 「宿主吃掉 token 块之后第一条规则」——也假,真因是 tokens 模板字符串结尾多了一个反斜杠,\\n 注入文本里留下字面反引号,把紧随其后的那条规则的选择器污染掉了(见 dsh-host.md §9)。\\n 样式照常多行书写,不必压行;也不需要任何「牺牲规则」。 */\\n/* 外观只有一套(2026-10-26):原 variant 的 default / inset 两档在 CSS 里只差 1px 内距,\\n 且 default 比文档承诺矮 2px,却让下游以为「有得选」而反复对图 ⇒ 整轴删除。\\n padding 3px 是尺寸契约的一部分:item 高度 = 控制高 − 6px,加起来正好 24 / 28 / 32。 */\\n.dshpc-seg{display:inline-flex;align-items:center;gap:2px;padding:3px;border-radius:var(--dshpc-radius-md);--seg-thumb:var(--dshpc-surface-raised);background:var(--dshpc-seg-track);}\\n.dshpc-seg__item{appearance:none;display:inline-flex;align-items:center;gap:4px;box-sizing:border-box;height:calc(var(--dshpc-control-h-sm) - 6px);padding:0 12px;border:0;border-radius:var(--dshpc-radius-sm);background:transparent;color:var(--dshpc-fg-2);font-family:inherit;font-size:var(--dshpc-font-xs);font-weight:500;white-space:nowrap;cursor:pointer;flex:none;transition:color var(--dshpc-dur-fast) var(--dshpc-ease),background-color var(--dshpc-dur-fast) var(--dshpc-ease),box-shadow var(--dshpc-dur-fast) var(--dshpc-ease);}\\n.dshpc-seg--md .dshpc-seg__item{height:calc(var(--dshpc-control-h-md) - 6px);}\\n.dshpc-seg--lg .dshpc-seg__item{height:calc(var(--dshpc-control-h-lg) - 6px);}\\n.dshpc-seg__item:hover:not([aria-pressed='true']):not(:disabled){color:var(--dshpc-fg);}\\n.dshpc-seg__item[aria-pressed='true']{background:var(--seg-thumb);box-shadow:var(--dshpc-shadow-raised);color:var(--dshpc-fg);font-weight:600;}\\n.dshpc-seg__item:focus-visible{outline:2px solid var(--dshpc-focus);outline-offset:-2px;}\\n.dshpc-seg__item:disabled{cursor:default;opacity:.4;}\\n/* 段内角标(如「异常」的数量):语义色实面 + 反白字,0 由组件侧不渲染。必须是正圆(用户 2026-10-03)。 */\\n.dshpc-seg__badge{display:inline-flex;align-items:center;justify-content:center;flex:none;width:16px;height:16px;padding:0;overflow:hidden;border-radius:50%;background:var(--dshpc-danger);color:var(--dshpc-on-signal);font-size:10px;line-height:16px;font-weight:500;font-variant-numeric:tabular-nums;}\\n/* 段内中性计数(如筛选条「全部 11」):纯文字、无底无边(对齐 task-ledger .dtl-seg__num 拍板口径);0 由组件侧不渲染。 */\\n.dshpc-seg__count{display:inline;flex:none;margin-left:3px;padding:0;border:0;border-radius:0;background:none;color:var(--dshpc-fg-3);font-size:10px;line-height:1;font-weight:400;font-variant-numeric:tabular-nums;}\\n/* block:撑满父宽(表单行用),各段等分 */\\n.dshpc-seg--block{display:flex;width:100%;}\\n.dshpc-seg--block .dshpc-seg__item{flex:1 1 auto;justify-content:center;}\\n/* weekday:星期多选方块。基础插件的特殊化定制(用户 2026-10-01:原 WeekdayPicker 即「蓝底 + 近似方形」):\\n 每格正方形(宽 = 段高)、选中品牌蓝反白字、**无外描边**(2026-10-18 重申)、\\n 方块之间间距 gap:2px(2026-10-20 用户定稿:方块改小后 6px 显得太宽。10-18 曾从 2px 放宽到 6px,\\n 两次都是用户拍板 —— 别自作主张改回去)。 */\\n.dshpc-seg--weekday{--seg-track:var(--dshpc-seg-track);gap:2px;border:0;padding:3px;background:var(--seg-track);}\\n.dshpc-seg--weekday .dshpc-seg__item{width:calc(var(--dshpc-control-h-lg) - 8px);padding:0;justify-content:center;}\\n.dshpc-seg--weekday .dshpc-seg__item[aria-pressed='true']{background:var(--dshpc-business);color:var(--dshpc-fg-inverse);box-shadow:var(--dshpc-shadow-raised);}\\n\\n/* ── 单选滑动块(2026-10-26 用户:点选后选中底应「滑过去」,不是旧段消失、新段直接亮)。\\n 结构 = 一块绝对定位的共用底 + 各段透明;位置/尺寸由组件量出后内联,这里只管外观与过渡。\\n --slide 只在单选挂上:多选(如星期)每段各自着色,没有唯一滑块可滑,保持原样。 */\\n.dshpc-seg--slide{position:relative;}\\n.dshpc-seg--slide .dshpc-seg__item{position:relative;z-index:1;}\\n.dshpc-seg--slide .dshpc-seg__item[aria-pressed='true']{background:transparent;box-shadow:none;}\\n.dshpc-seg__thumb{position:absolute;z-index:0;border-radius:var(--dshpc-radius-sm);background:var(--seg-thumb);box-shadow:var(--dshpc-shadow-raised);pointer-events:none;transition:left var(--dshpc-dur) var(--dshpc-ease),top var(--dshpc-dur) var(--dshpc-ease),width var(--dshpc-dur) var(--dshpc-ease),height var(--dshpc-dur) var(--dshpc-ease);}\\n.dshpc-seg--weekday.dshpc-seg--slide .dshpc-seg__thumb{background:var(--dshpc-business);}\\n\\n/* ── bordered 外框(2026-10-20 用户要的第二种模式):**只在最外面套一圈 1px 描边**,\\n 里面一概不动 —— 选中片的填充色 / 阴影 / 文字色全部保持原样(weekday 的蓝面照旧),\\n 这里不写任何针对 __item 的规则。\\n 总高必须与无框版逐像素一致:border 1px×2 由 padding 各让 1px 抵消(3 → 2);\\n weekday 自己声明的 3px 在文件更后面,靠双类选择器压回 2px。 */\\n.dshpc-seg--bordered{border:1px solid var(--dshpc-border);padding:2px;}\\n.dshpc-seg--bordered.dshpc-seg--weekday{padding:2px;}\\n\\n@media (prefers-reduced-motion: reduce){.dshpc-seg__item{transition:none;}.dshpc-seg__thumb{transition:none;}}\\n\";\n//# sourceMappingURL=segmented-css.generated.js.map","// ⚠️ 生成物,勿手改。真源 = src/ui/controls/button.css\n// 由 scripts/gen-css.mjs 生成(`pnpm run gen:css`):改样式请改那个 .css 文件后重新生成。\nexport const BUTTON_CSS = \"\\n/* ── 按钮 / 图标钮 P2 ───────────────────────────────────────────────────\\n 与 Segmented 同一条高度纪律:--dshpc-control-h-sm(24) / -md(28) / -lg(32),\\n 有边框的 variant 用 1px 真边框 + 内部 padding 补回,**有边 / 无边同高**。\\n\\n 三条受控轴(2026-10-19 重写,对齐主流 UI 框架的分类口径):\\n · variant —— 外观档 = 形态 + 语义色,共 10 档:\\n primary / secondary / outline / ghost / danger / success / warning / info /\\n danger-outline(红字描边)/ link(行内链接)\\n · size —— sm / md / lg\\n · block —— 撑满父宽\\n 每一档**只填 5 个局部变量**(--btn-bg / -fg / -border / -bg-hover / -bg-active),\\n 结构与交互只有上面这一份;任何档位都不许再写一遍 display/height/padding。\\n 自定义颜色(Button 的 color 参数)同样只覆盖这 5 个变量(token 覆盖,不是新皮肤)。\\n\\n ⚠️ hover 不再用 opacity 压一层(用户 2026-10-19:「黑色和红色的按钮移上去变化太小,\\n 完全感觉不到颜色变了」)⇒ 走 --dshpc-*-hover / -active 的明确混色,见 tokens-css.ts。 */\\n.dshpc-btn{--btn-bg:transparent;--btn-fg:var(--dshpc-fg);--btn-border:transparent;--btn-pad:12px;\\n --btn-bg-hover:var(--dshpc-hover);--btn-bg-active:var(--dshpc-active);--btn-fg-hover:var(--btn-fg);\\n appearance:none;display:inline-flex;align-items:center;justify-content:center;gap:6px;\\n box-sizing:border-box;border:1px solid var(--btn-border);border-radius:var(--dshpc-radius-md);\\n background-color:var(--btn-bg);color:var(--btn-fg);font-family:inherit;font-weight:500;white-space:nowrap;cursor:pointer;\\n transition:background-color var(--dshpc-dur-fast) var(--dshpc-ease),border-color var(--dshpc-dur-fast) var(--dshpc-ease),color var(--dshpc-dur-fast) var(--dshpc-ease),box-shadow var(--dshpc-dur-fast) var(--dshpc-ease),transform var(--dshpc-dur-fast) var(--dshpc-ease);}\\n.dshpc-btn--sm{--btn-pad:10px;height:var(--dshpc-control-h-sm);padding:0 var(--btn-pad);font-size:var(--dshpc-font-sm);line-height:1;}\\n.dshpc-btn--md{--btn-pad:12px;height:var(--dshpc-control-h-md);padding:0 var(--btn-pad);font-size:var(--dshpc-font-md);line-height:1;}\\n.dshpc-btn--lg{--btn-pad:14px;height:var(--dshpc-control-h-lg);padding:0 var(--btn-pad);font-size:var(--dshpc-font-md);line-height:1;}\\n/* block:撑满父宽(表单底栏 / 抽屉底部的主操作) */\\n.dshpc-btn--block{display:flex;width:100%;}\\n/* block + 前置图标 ⇒ 文字视觉居中(2026-10-19 用户点名):\\n 内容组 [图标 + 间距 + 文字] 整体在盒内居中时,**文字**的中心会被图标推右半格。\\n 把右内边距补上「图标宽 + 间距」,可用盒随之左移同量 ⇒ 文字落回视觉中心,图标贴左侧。\\n 图标宽按 1.2em 估(官方图标 14/16px vs 字号 12/13px),em 随字号档自动缩放。 */\\n.dshpc-btn--block.dshpc-btn--icon-start{padding-right:calc(var(--btn-pad) + 1.2em + 6px);}\\n.dshpc-btn__icon,.dshpc-btn__icon-end{display:inline-flex;align-items:center;justify-content:center;flex:none;line-height:0;}\\n.dshpc-btn__icon svg,.dshpc-btn__icon-end svg{display:block;margin:0;}\\n/* loading:不换 DOM 结构,只在文案前插一个同色小圈。\\n ⚠️ 2026-10-20 改画法:原来是 border:1.5px 加 border-radius:999px 画的环 —— 真机实测 computed\\n radius 就是 999px、宽高都是 12px(没被任何样式覆盖),看着却\\\"像圆角方\\\",原因是**次像素边框\\n (1.5px)在 12px 这么小的圆上被抗锯齿插值拉毛**。改用 SVG 矢量弧:任意 DPR 下都是真圆。 */\\n.dshpc-btn__spinner{display:block;flex:none;width:12px;height:12px;\\n animation:dshpc-btn-spin .7s linear infinite;}\\n/* shortcut: 12px 是固定值,不随按钮字号缩放;要更大就改这一处。 */\\n@keyframes dshpc-btn-spin{to{transform:rotate(360deg)}}\\n\\n/* 交互态:颜色变化写在变量上 ⇒ 所有档位一次生效,且变化幅度由 token 决定(够明显) */\\n.dshpc-btn:hover:not(:disabled){background-color:var(--btn-bg-hover);color:var(--btn-fg-hover);}\\n.dshpc-btn:active:not(:disabled){background-color:var(--btn-bg-active);transform:translateY(1px);}\\n.dshpc-btn:focus-visible{outline:2px solid var(--dshpc-focus);outline-offset:2px;}\\n.dshpc-btn:disabled{cursor:default;opacity:.5;}\\n\\n.dshpc-btn--primary{--btn-bg:var(--dshpc-accent);--btn-fg:var(--dshpc-fg-inverse);\\n --btn-bg-hover:var(--dshpc-accent-hover);--btn-bg-active:var(--dshpc-accent-active);}\\n/* secondary:中性实心(灰面),用于「取消 / 次要」这类与主操作并排的按钮 */\\n.dshpc-btn--secondary{--btn-bg:var(--dshpc-hover);--btn-fg:var(--dshpc-fg);\\n --btn-bg-hover:var(--dshpc-active);--btn-bg-active:var(--dshpc-active);}\\n.dshpc-btn--outline{--btn-bg:var(--dshpc-surface-1);--btn-border:var(--dshpc-border-strong);\\n --btn-bg-hover:var(--dshpc-hover);--btn-bg-active:var(--dshpc-active);}\\n.dshpc-btn--ghost{--btn-fg:var(--dshpc-fg-2);--btn-fg-hover:var(--dshpc-fg);\\n --btn-bg-hover:var(--dshpc-hover);--btn-bg-active:var(--dshpc-active);}\\n.dshpc-btn--danger{--btn-bg:var(--dshpc-danger);--btn-fg:var(--dshpc-on-signal);\\n --btn-bg-hover:var(--dshpc-danger-hover);--btn-bg-active:var(--dshpc-danger-active);}\\n.dshpc-btn--success{--btn-bg:var(--dshpc-success);--btn-fg:var(--dshpc-on-signal);\\n --btn-bg-hover:var(--dshpc-success-hover);--btn-bg-active:var(--dshpc-success-active);}\\n.dshpc-btn--warning{--btn-bg:var(--dshpc-warning);--btn-fg:var(--dshpc-on-warning);\\n --btn-bg-hover:var(--dshpc-warning-hover);--btn-bg-active:var(--dshpc-warning-active);}\\n.dshpc-btn--info{--btn-bg:var(--dshpc-business);--btn-fg:var(--dshpc-on-signal);\\n --btn-bg-hover:var(--dshpc-business-hover);--btn-bg-active:var(--dshpc-business-active);}\\n/* danger-outline:红字描边(破坏性次要操作,如卡片上的「删除」)。\\n ⚠️ 旧修饰类 danger-ink 保留为别名(消费方可能还在挂),两者同一套皮肤。 */\\n.dshpc-btn--danger-outline,.dshpc-btn--danger-ink{--btn-border:var(--dshpc-danger);--btn-fg:var(--dshpc-danger);\\n --btn-fg-hover:var(--dshpc-danger);--btn-bg-hover:var(--dshpc-danger-soft);--btn-bg-active:var(--dshpc-danger-soft);}\\n/* link:行内文字链接型(会话 / 产出文件名),无底无边、品牌蓝、hover 下划线 */\\n.dshpc-btn--link{--btn-fg:var(--dshpc-link);--btn-fg-hover:var(--dshpc-link);\\n --btn-bg-hover:transparent;--btn-bg-active:transparent;\\n height:auto;padding:0;border:0;background:none;font-weight:400;text-align:left;}\\n.dshpc-btn--link:hover:not(:disabled){text-decoration:underline;}\\n\\n/* 图标钮:纯图标,方形;尺寸档的宽高与同档文字按钮等高 */\\n.dshpc-iconbtn{appearance:none;display:inline-flex;align-items:center;justify-content:center;box-sizing:border-box;\\n border:1px solid transparent;border-radius:var(--dshpc-radius-sm);background:transparent;color:var(--dshpc-fg-2);\\n font-family:inherit;cursor:pointer;flex:none;\\n transition:background-color var(--dshpc-dur-fast) var(--dshpc-ease),border-color var(--dshpc-dur-fast) var(--dshpc-ease),color var(--dshpc-dur-fast) var(--dshpc-ease),opacity var(--dshpc-dur-fast) var(--dshpc-ease);}\\n.dshpc-iconbtn--sm{width:var(--dshpc-control-h-sm);height:var(--dshpc-control-h-sm);font-size:var(--dshpc-font-sm);}\\n.dshpc-iconbtn--md{width:var(--dshpc-control-h-md);height:var(--dshpc-control-h-md);font-size:var(--dshpc-font-md);}\\n.dshpc-iconbtn--lg{width:var(--dshpc-control-h-lg);height:var(--dshpc-control-h-lg);font-size:var(--dshpc-font-md);}\\n.dshpc-iconbtn--plain{color:var(--dshpc-fg-2);}\\n.dshpc-iconbtn--outline{background:var(--dshpc-surface-1);border-color:var(--dshpc-border);color:var(--dshpc-fg-2);}\\n.dshpc-iconbtn--danger{color:var(--dshpc-danger);}\\n.dshpc-iconbtn:hover:not(:disabled){background:var(--dshpc-hover);color:var(--dshpc-fg);}\\n.dshpc-iconbtn--danger:hover:not(:disabled){background:var(--dshpc-danger-soft);color:var(--dshpc-danger);}\\n.dshpc-iconbtn:focus-visible{outline:2px solid var(--dshpc-focus);outline-offset:2px;}\\n.dshpc-iconbtn:disabled{cursor:default;opacity:.4;}\\n\\n/* ── 行式文件按钮(图标 + 文件名)P2:**全站唯一实现**(2026-10-04 收编)──────────\\n 用途:「产出物 / 附件」那种**一行一个文件**的清单项(基础信息右栏产出物清单、附件区、\\n 执行记录页的展开区)。平时透明、**鼠标移上去才出浅底**(沿用用户 2026-10-03 定的观感)。\\n 两个形态修饰类:\\n --block 撑满父宽(清单里一项一行)\\n --inline 内容宽(跟在文字后头,如附件行)\\n 收编原因:这份皮肤此前只写在 task-list.tsx 的 TASK_LIST_CSS 里(旧名 .dshpc-info-out),\\n 执行记录页展开区要用同一种观感 ⇒ 上提基础层,避免再出现「各写一份外观」(同名不同皮的坑刚踩过)。 */\\n.dshpc-filechip{appearance:none;-webkit-appearance:none;border:0;border-radius:var(--dshpc-radius-xs);\\n background:transparent;color:var(--dshpc-fg);font:inherit;text-align:left;cursor:pointer;min-width:0;\\n transition:background-color var(--dshpc-dur) var(--dshpc-ease);}\\n.dshpc-filechip:hover:not(:disabled){background:var(--dshpc-chip-bg);}\\n.dshpc-filechip:focus-visible{outline:2px solid var(--dshpc-focus);outline-offset:1px;}\\n.dshpc-filechip:disabled{cursor:default;background:transparent;color:var(--dshpc-fg-3);}\\n.dshpc-filechip--block{display:flex;align-items:center;gap:6px;width:100%;box-sizing:border-box;\\n padding:4px 6px;font-size:var(--dshpc-font-xs);}\\n.dshpc-filechip--inline{display:inline-flex;align-items:center;gap:4px;padding:2px 6px;font-size:var(--dshpc-font-sm);}\\n\\n@media (prefers-reduced-motion: reduce){.dshpc-btn,.dshpc-iconbtn,.dshpc-filechip{transition:none;}}\\n\";\n//# sourceMappingURL=button-css.generated.js.map","// ⚠️ 生成物,勿手改。真源 = src/ui/controls/field.css\n// 由 scripts/gen-css.mjs 生成(`pnpm run gen:css`):改样式请改那个 .css 文件后重新生成。\nexport const FIELD_CSS = \"\\n/* ── 字段 + 问号提示(hint 参数内置) ──────────────────────────────────── */\\n/* 控件 + FieldHint 同一行;hint 版由组件自己包,调用方只传 hint 字符串。\\n 铺满型控件(input/textarea)进包后改吃 flex 弹性,让位给问号。 */\\n.dshpc-fieldwrap{display:flex;align-items:center;gap:6px;min-width:0;max-width:100%;}\\n.dshpc-fieldwrap--inline{display:inline-flex;}\\n.dshpc-fieldwrap > .dshpc-input,.dshpc-fieldwrap > .dshpc-textarea{flex:1 1 auto;width:auto;min-width:0;}\\n/* 多行输入:问号钉在**右下角**(2026-10-20 用户:不要垂直居中),文本区底部留出它的位置。\\n ⚠️ 这一档必须把 textarea 的宽度还回去(上面那条 flex 让位规则会把它缩窄)。 */\\n.dshpc-fieldwrap--block{position:relative;display:block;}\\n.dshpc-fieldwrap--block > .dshpc-textarea{width:100%;padding-bottom:24px;}\\n.dshpc-fieldwrap--block > .dshpc-hint{position:absolute;right:8px;bottom:6px;}\\n\\n/* ── 输入类 P3 ────────────────────────────────────────────────────────── */\\n/* 默认铺满容器(width:100%,与 .dshpc-textarea 同口径):input 原生按 size 属性取内在宽,\\n 不铺满 ⇒ 调用方套定宽壳时会「右边空一截、看着没贴右」(2026-10-20 用户抓的 bug)。\\n 要定宽由调用方在外面套壳控制(如 192px 搜索槽)。 */\\n.dshpc-input{display:block;width:100%;box-sizing:border-box;border:1px solid var(--dshpc-border);border-radius:var(--dshpc-radius-md);\\n background:var(--dshpc-surface-1);color:var(--dshpc-fg);font-family:inherit;outline:none;\\n transition:border-color var(--dshpc-dur-fast) var(--dshpc-ease),box-shadow var(--dshpc-dur-fast) var(--dshpc-ease);}\\n.dshpc-input--sm{height:var(--dshpc-control-h-sm);padding:0 8px;font-size:var(--dshpc-font-sm);line-height:var(--dshpc-line-sm);}\\n.dshpc-input--md{height:var(--dshpc-control-h-md);padding:0 10px;font-size:var(--dshpc-font-md);line-height:var(--dshpc-line-md);}\\n.dshpc-input--lg{height:var(--dshpc-control-h-lg);padding:0 12px;font-size:var(--dshpc-font-md);line-height:var(--dshpc-line-md);}\\n.dshpc-input::placeholder{color:var(--dshpc-fg-dim);}\\n.dshpc-input:focus{border-color:var(--dshpc-focus);box-shadow:0 0 0 1px var(--dshpc-focus);}\\n.dshpc-input--error{border-color:var(--dshpc-danger);}\\n.dshpc-input:disabled{cursor:default;opacity:.5;}\\n\\n.dshpc-pfx{display:inline-flex;align-items:center;box-sizing:border-box;overflow:hidden;\\n border:1px solid var(--dshpc-border);border-radius:var(--dshpc-radius-md);background:var(--dshpc-surface-1);color:var(--dshpc-fg);}\\n.dshpc-pfx--sm{height:var(--dshpc-control-h-sm);}\\n.dshpc-pfx--md{height:var(--dshpc-control-h-md);}\\n.dshpc-pfx--lg{height:var(--dshpc-control-h-lg);}\\n/* md / lg 档字号跟档走(与同档下拉同字号):此前写死 sm(12px),同排下拉是 13px ⇒ 显得「input 字小」。 */\\n.dshpc-pfx--md .dshpc-pfx__label,.dshpc-pfx--lg .dshpc-pfx__label{font-size:var(--dshpc-font-md);line-height:var(--dshpc-line-md);}\\n.dshpc-pfx--md .dshpc-pfx__input,.dshpc-pfx--lg .dshpc-pfx__input{font-size:var(--dshpc-font-md);line-height:var(--dshpc-line-md);}\\n.dshpc-pfx--error{border-color:var(--dshpc-danger);}\\n.dshpc-pfx:focus-within{border-color:var(--dshpc-focus);box-shadow:0 0 0 1px var(--dshpc-focus);}\\n.dshpc-pfx__label{padding:0 8px;color:var(--dshpc-fg-2);font-size:var(--dshpc-font-sm);line-height:var(--dshpc-line-sm);white-space:nowrap;border-right:1px solid var(--dshpc-border);}\\n.dshpc-pfx__input{flex:1 1 auto;min-width:0;height:100%;padding:0 8px;border:0;background:transparent;color:var(--dshpc-fg);\\n font-family:inherit;font-size:var(--dshpc-font-sm);line-height:var(--dshpc-line-sm);outline:none;}\\n.dshpc-pfx__input::placeholder{color:var(--dshpc-fg-dim);}\\n\\n.dshpc-num{display:inline-flex;align-items:center;justify-content:space-between;box-sizing:border-box;overflow:hidden;\\n border:1px solid var(--dshpc-border);border-radius:var(--dshpc-radius-md);background:var(--dshpc-surface-1);color:var(--dshpc-fg);}\\n/* 中段:数字 + 后缀成组居中;容器被消费端拉宽时吃掉全部余量,两端 − / + 因此钉死在左右边缘。 */\\n.dshpc-num__mid{display:flex;align-items:center;justify-content:center;flex:1 1 auto;min-width:0;}\\n.dshpc-num--sm{height:var(--dshpc-control-h-sm);}\\n.dshpc-num--md{height:var(--dshpc-control-h-md);}\\n.dshpc-num--lg{height:var(--dshpc-control-h-lg);}\\n.dshpc-num--md .dshpc-num__input,.dshpc-num--lg .dshpc-num__input{font-size:var(--dshpc-font-md);line-height:var(--dshpc-line-md);}\\n.dshpc-num--md .dshpc-num__suffix,.dshpc-num--lg .dshpc-num__suffix{font-size:var(--dshpc-font-md);}\\n.dshpc-num--disabled{opacity:.5;}\\n/* 焦点态与 Input 同款(2026-10-20 用户:数字框里点进去没有蓝框):内层 input 无边框,\\n 焦点状态画在整个步进控件外框上。 */\\n.dshpc-num:focus-within{border-color:var(--dshpc-focus);box-shadow:0 0 0 1px var(--dshpc-focus);}\\n.dshpc-num__input{width:36px;height:100%;padding:0 2px;border:0;background:transparent;color:var(--dshpc-fg);\\n font-family:inherit;font-size:var(--dshpc-font-sm);line-height:var(--dshpc-line-sm);text-align:center;outline:none;}\\n.dshpc-num__suffix{padding:0 6px;color:var(--dshpc-fg-2);font-size:var(--dshpc-font-sm);white-space:nowrap;}\\n.dshpc-num .dshpc-iconbtn{border-radius:0;color:var(--dshpc-fg-2);flex:none;}\\n\\n/* 官方 Switch 包装统一:选中 = success 绿。\\n (合并原先 task-editor-css / task-list 两处就地覆盖;选择器带包装类 + role,特异性高于官方。) */\\n.dshpc-switch button[role='switch'][aria-checked='true']{background:var(--dshpc-success);}\\n\\n/* 多行文本输入(提示词等,P3):**边框 / 圆角 / 底 / 焦点态与 Input 同一套口径**(用户 2026-10-20:\\n 「多行输入应该和 input 的边儿是一个道理,包括圆角在内,都是一个东西」)。\\n ⚠️ 旧意图「卡内无边框、视觉重心在整张卡上」已作废 —— 现在它就是一只带框的多行输入框。\\n (从 task-editor-css 的 .dshpc-ed-prompt 上提而来;业务文件不再自写 textarea 皮肤。) */\\n.dshpc-textarea{display:block;width:100%;box-sizing:border-box;min-height:132px;padding:8px 12px;\\n border:1px solid var(--dshpc-border);border-radius:var(--dshpc-radius-md);outline:none;\\n background:var(--dshpc-surface-1);color:var(--dshpc-fg);font-family:inherit;font-size:var(--dshpc-font-lg);line-height:1.6;resize:vertical;\\n transition:border-color var(--dshpc-dur-fast) var(--dshpc-ease),box-shadow var(--dshpc-dur-fast) var(--dshpc-ease);}\\n.dshpc-textarea::placeholder{color:var(--dshpc-fg-dim);}\\n.dshpc-textarea:focus{border-color:var(--dshpc-focus);box-shadow:0 0 0 1px var(--dshpc-focus);}\\n/* 校验不通过:与 Input 一致,走边框描红(旧版是 box-shadow 描红盒,与 Input 不同口径) */\\n.dshpc-textarea--error{border-color:var(--dshpc-danger);}\\n.dshpc-textarea:disabled{cursor:default;opacity:.5;}\\n@media (prefers-reduced-motion: reduce){.dshpc-textarea{transition:none;}}\\n\\n/* 拖拽分隔条(编辑分栏 / 预览 dock 共用,U20 #3):6px 命中区,col-resize,不画线,hover/按下浮出浅带。\\n 具体 z-index 由 .dshpc-ed-resizer / .dshpc-sv-resizer 各自补。 */\\n.dshpc-resizer{position:absolute;top:0;bottom:0;left:0;width:6px;cursor:col-resize;background:0 0;touch-action:none;user-select:none;}\\n.dshpc-resizer:hover,.dshpc-resizer:active{background:var(--dshpc-hover,rgba(38,49,72,.06));}\\n\\n@media (prefers-reduced-motion: reduce){.dshpc-input,.dshpc-pfx{transition:none;}}\\n\";\n//# sourceMappingURL=field-css.generated.js.map","// ⚠️ 生成物,勿手改。真源 = src/ui/controls/loading.css\n// 由 scripts/gen-css.mjs 生成(`pnpm run gen:css`):改样式请改那个 .css 文件后重新生成。\nexport const LOADING_CSS = \"\\n/* 运行中 / loading 的活动指示:三个小方块依次脉动。 */\\n@keyframes dshpc-run-block { 0%, 80%, 100% { opacity: 0.25; transform: scale(0.8) } 40% { opacity: 1; transform: scale(1) } }\\n.dshpc-run-blocks { display: inline-flex; align-items: center; gap: 3px; }\\n.dshpc-run-blocks > i { width: 5px; height: 5px; border-radius: 1px; background: currentColor; animation: dshpc-run-block 1.2s ease-in-out infinite; }\\n.dshpc-run-blocks > i:nth-child(2) { animation-delay: 0.15s; }\\n.dshpc-run-blocks > i:nth-child(3) { animation-delay: 0.3s; }\\n@media (prefers-reduced-motion: reduce) { .dshpc-run-blocks > i { animation: none; opacity: 1; } }\\n\";\n//# sourceMappingURL=loading-css.generated.js.map","// ⚠️ 生成物,勿手改。真源 = src/ui/controls/back-to-top.css\n// 由 scripts/gen-css.mjs 生成(`pnpm run gen:css`):改样式请改那个 .css 文件后重新生成。\nexport const BACK_TO_TOP_CSS = \"\\n/* 回到顶部悬浮钮:圆钮、实面、投影;默认隐身,滚过阈值加 .is-visible 才显形。\\n 横向 left 由组件按主内容列右缘实时算出(贴在其右侧外侧),不写死。 */\\n.dshpc-backtotop{\\n position:fixed;\\n bottom:var(--dshpc-space-4);\\n z-index:var(--dshpc-z-dock);\\n width:44px;height:44px;\\n display:inline-flex;align-items:center;justify-content:center;\\n padding:0;margin:0;\\n box-sizing:border-box;\\n border:1px solid var(--dshpc-border);\\n border-radius:50%;\\n background:var(--dshpc-solid);\\n color:var(--dshpc-on-solid);\\n box-shadow:var(--dshpc-shadow-2);\\n cursor:pointer;\\n opacity:0;\\n transform:translateY(8px) scale(.92);\\n transition:opacity var(--dshpc-dur) var(--dshpc-ease),\\n transform var(--dshpc-dur) var(--dshpc-ease),\\n background-color var(--dshpc-dur-fast) var(--dshpc-ease);\\n pointer-events:none;\\n}\\n.dshpc-backtotop.is-visible{opacity:1;transform:translateY(0) scale(1);pointer-events:auto;}\\n.dshpc-backtotop:hover{background:var(--dshpc-hover);}\\n.dshpc-backtotop:active{background:var(--dshpc-active);}\\n.dshpc-backtotop:focus-visible{outline:2px solid var(--dshpc-focus);outline-offset:2px;}\\n@media (prefers-reduced-motion: reduce){\\n .dshpc-backtotop{transition:opacity var(--dshpc-dur-fast) linear;transform:none;}\\n}\\n\";\n//# sourceMappingURL=back-to-top-css.generated.js.map","// ⚠️ 生成物,勿手改。真源 = src/ui/controls/hint.css\n// 由 scripts/gen-css.mjs 生成(`pnpm run gen:css`):改样式请改那个 .css 文件后重新生成。\nexport const HINT_CSS = \"\\n/* ── 问号提示 P4(用户 2026-10-18:对齐真实插件 HelpButton——**带圈的问号图标**)──\\n 本体 14px 细圈 + 圈内 ?,颜色 fg-3、hover 只提亮不加底(与 dshpc-ed-help 同规矩)。\\n 气泡不在本文件:2026-10-19 用户拍板「问号必须用官方 Tooltip 那一个」⇒ 气泡由注入的\\n 官方组件渲染(src/ui/tooltip.ts),这里只管问号图标本身。 */\\n.dshpc-hint{display:inline-flex;align-items:center;justify-content:center;flex:none;\\n box-sizing:border-box;width:14px;height:14px;padding:0;border:1px solid currentColor;border-radius:50%;background:transparent;\\n color:var(--dshpc-fg-3);font-family:inherit;font-size:8px;font-weight:600;line-height:12px;cursor:help;vertical-align:middle;\\n transition:color var(--dshpc-dur-fast) var(--dshpc-ease);}\\n.dshpc-hint:hover,.dshpc-hint:focus-visible{color:var(--dshpc-fg);background:0 0;}\\n.dshpc-hint:focus-visible{outline:2px solid var(--dshpc-focus);outline-offset:1px;}\\n\";\n//# sourceMappingURL=hint-css.generated.js.map","// ⚠️ 生成物,勿手改。真源 = src/ui/controls/datetime.css\n// 由 scripts/gen-css.mjs 生成(`pnpm run gen:css`):改样式请改那个 .css 文件后重新生成。\nexport const DATETIME_CSS = \"/* 日期时间选择器(DateTimePicker)。类名 dshpc-dt-*;配色只吃 token,明暗随 token 切换。\\n 结构:触发器(range = 一个整条:两个日期区 + 样式画的灰隔条;single = 单日期)→ 浮层\\n (两个独立端框 + 两块独立日历 + 底部动作)。\\n 浮层行为与 Picker 一致:portal 到 body、贴边翻转、点外关闭、无遮罩。 */\\n.dshpc-dt{position:relative;display:inline-block;font-size:13px;line-height:20px}\\n.dshpc-dt__trigger{\\n display:inline-flex;align-items:center;justify-content:space-between;gap:6px;\\n max-width:100%;height:var(--dshpc-control-h-md);padding:0 8px;\\n color:var(--dshpc-fg);background:var(--dshpc-surface-1);\\n border:1px solid var(--dshpc-border);border-radius:var(--dshpc-radius-md);cursor:pointer;\\n}\\n.dshpc-dt__trigger--sm{height:var(--dshpc-control-h-sm);font-size:12px}\\n.dshpc-dt__trigger--lg{height:var(--dshpc-control-h-lg)}\\n.dshpc-dt__trigger:disabled{color:var(--dshpc-fg-dim);cursor:not-allowed;opacity:.7}\\n/* 焦点与基础 Input 完全同款(点击即蓝描边 + 1px 光环)。 */\\n.dshpc-dt__trigger:focus{border-color:var(--dshpc-focus);box-shadow:0 0 0 1px var(--dshpc-focus)}\\n.dshpc-dt__trigger-label{flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;text-align:left;font-variant-numeric:tabular-nums}\\n.dshpc-dt__trigger-label--empty{color:var(--dshpc-fg-dim)}\\n.dshpc-dt__cal{flex:none;color:var(--dshpc-fg-3)}\\n/* range 触发器:一个整条里两个日期区 + 样式画出来的灰隔条(左右两条竖边),点整条都展开。 */\\n/* 组撑满触发器内容高度,隔条才能上下顶到 border。 */\\n.dshpc-dt__pair-group{flex:1 1 auto;min-width:0;align-self:stretch;display:flex;align-items:center;gap:8px}\\n/* 两个日期区平分(flex:1 1 0):开始 / 结束永远一样宽,不随内容偏袒。 */\\n.dshpc-dt__pair-date{flex:1 1 0;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-variant-numeric:tabular-nums}\\n.dshpc-dt__pair-date--empty{color:var(--dshpc-fg-dim)}\\n/* 隔条:上下顶到触发器 border(与边框连起来),中间隔出一块;块里放「到」的符号(-,用户 2026-10-24 拍板)。 */\\n.dshpc-dt__pair-sep{\\n flex:none;align-self:stretch;width:22px;margin:0;\\n display:inline-flex;align-items:center;justify-content:center;\\n background:var(--dshpc-surface-sunken);\\n border-left:1px solid var(--dshpc-border);border-right:1px solid var(--dshpc-border);\\n color:var(--dshpc-fg-3);font-size:12px;line-height:1;\\n}\\n/* 默认宽:**固定**(选中前后不变),数值对照参考图实测(2x 屏,换算 CSS px)后\\n 统一 -6px(用户 2026-10-24:实测值留得偏多):\\n 单值 day 128 / 时·分 153.2 / 秒 174.8;区间 day 269 / 分 341.4 / 秒 377.6。\\n ch = 字体里 \\\"0\\\" 的宽(日期 tabular-nums 等宽)⇒ 写成 Nch + 常数;常数同时兜住\\n 默认占位「请选择日期时间」(7 汉字)不省略。调用方要另给宽:className 传 width。 */\\n.dshpc-dt__trigger--w-day{width:calc(10ch + 56px)}\\n.dshpc-dt__trigger--w-minute{width:calc(16ch + 38px)}\\n.dshpc-dt__trigger--w-second{width:calc(19ch + 38px)}\\n.dshpc-dt__trigger--wr-day{width:calc(20ch + 125px)}\\n.dshpc-dt__trigger--wr-minute{width:calc(32ch + 111px)}\\n.dshpc-dt__trigger--wr-second{width:calc(38ch + 104px)}\\n\\n.dshpc-dt__pop{\\n z-index:60;padding:10px;user-select:none;\\n font-size:13px;line-height:20px;\\n background:var(--dshpc-surface-menu);border:1px solid var(--dshpc-border);\\n border-radius:var(--dshpc-radius-md);box-shadow:0 8px 24px rgba(15,23,42,.12);\\n}\\n/* 两个独立端框(range):点哪个哪个成为当前编辑端,互不联动、只是排在一起。 */\\n.dshpc-dt__ends{display:flex;gap:6px;margin-bottom:8px}\\n.dshpc-dt__end{\\n flex:1 1 0;min-width:0;display:flex;align-items:center;gap:6px;padding:4px 8px;\\n text-align:left;background:var(--dshpc-surface-1);\\n border:1px solid var(--dshpc-border-faint);border-radius:var(--dshpc-radius-sm);cursor:pointer;\\n}\\n.dshpc-dt__end--active{border-color:var(--dshpc-business);background:var(--dshpc-open-bg)}\\n.dshpc-dt__end:focus-visible{outline:2px solid var(--dshpc-focus);outline-offset:1px}\\n.dshpc-dt__end-label{flex:none;font-size:11px;line-height:16px;color:var(--dshpc-fg-3);white-space:nowrap}\\n.dshpc-dt__end-value{font-size:12px;line-height:18px;color:var(--dshpc-fg);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-variant-numeric:tabular-nums}\\n.dshpc-dt__end-value--empty{color:var(--dshpc-fg-dim)}\\n\\n.dshpc-dt__nav{display:flex;align-items:center;justify-content:space-between;margin-bottom:6px}\\n.dshpc-dt__nav-group{display:flex;gap:2px}\\n.dshpc-dt__nav-btn{\\n display:inline-flex;align-items:center;justify-content:center;width:24px;height:24px;padding:0;\\n color:var(--dshpc-fg-2);background:none;border:0;border-radius:var(--dshpc-radius-sm);cursor:pointer;\\n}\\n.dshpc-dt__nav-btn:hover{background:var(--dshpc-surface-sunken);color:var(--dshpc-fg)}\\n.dshpc-dt__nav-btn:focus-visible{outline:2px solid var(--dshpc-focus);outline-offset:-1px}\\n.dshpc-dt__caption{font-size:13px;font-weight:600;color:var(--dshpc-fg);white-space:nowrap}\\n\\n.dshpc-dt__grid{display:grid;grid-template-columns:repeat(7,30px);gap:2px}\\n.dshpc-dt__wd{height:20px;font-size:11px;line-height:20px;color:var(--dshpc-fg-3);text-align:center}\\n.dshpc-dt__cell{\\n height:26px;padding:0;font-size:12px;font-variant-numeric:tabular-nums;\\n color:var(--dshpc-fg);background:none;border:0;border-radius:var(--dshpc-radius-sm);cursor:pointer;\\n}\\n.dshpc-dt__cell:hover{background:var(--dshpc-surface-sunken)}\\n.dshpc-dt__cell:focus-visible{outline:2px solid var(--dshpc-focus);outline-offset:-1px}\\n.dshpc-dt__cell--out{color:var(--dshpc-fg-dim)}\\n.dshpc-dt__cell--today{color:var(--dshpc-business);font-weight:600}\\n/* 起 / 止端:品牌蓝实面反白(与 Segmented weekday 选中同口径)。 */\\n.dshpc-dt__cell--sel{background:var(--dshpc-business);color:var(--dshpc-fg-inverse);font-weight:600}\\n.dshpc-dt__cell--sel:hover{background:var(--dshpc-business-hover)}\\n\\n/* 两块日历面板(range:左开始、右结束,各选各的)。 */\\n.dshpc-dt__panels{display:flex;gap:14px;align-items:flex-start}\\n.dshpc-dt__panel{display:flex;flex-direction:column;gap:6px}\\n\\n.dshpc-dt__time{display:flex;align-items:flex-end;justify-content:center;gap:4px;margin-top:2px;padding-top:8px;border-top:1px solid var(--dshpc-border-faint)}\\n.dshpc-dt__unit{display:flex;flex-direction:column;align-items:center;gap:2px}\\n.dshpc-dt__unit-label{font-size:10px;line-height:14px;color:var(--dshpc-fg-3)}\\n.dshpc-dt__step-btn{\\n display:inline-flex;align-items:center;justify-content:center;width:34px;height:14px;padding:0;\\n color:var(--dshpc-fg-2);background:none;border:0;border-radius:var(--dshpc-radius-sm);cursor:pointer;\\n}\\n.dshpc-dt__step-btn:hover{background:var(--dshpc-surface-sunken);color:var(--dshpc-fg)}\\n.dshpc-dt__step-btn:focus-visible{outline:2px solid var(--dshpc-focus);outline-offset:-1px}\\n.dshpc-dt__step-val{\\n width:34px;height:24px;padding:0;box-sizing:border-box;text-align:center;\\n font-size:13px;font-variant-numeric:tabular-nums;color:var(--dshpc-fg);\\n background:var(--dshpc-surface-sunken);border:1px solid var(--dshpc-border-faint);\\n border-radius:var(--dshpc-radius-sm);outline:none;\\n}\\n.dshpc-dt__step-val:focus{border-color:var(--dshpc-focus);box-shadow:0 0 0 1px var(--dshpc-focus)}\\n.dshpc-dt__step-val:disabled{color:var(--dshpc-fg-dim);cursor:not-allowed}\\n.dshpc-dt__sep{padding-bottom:5px;color:var(--dshpc-fg-3);font-size:12px}\\n\\n.dshpc-dt__foot{display:flex;align-items:center;justify-content:space-between;gap:8px;margin-top:8px;padding-top:8px;border-top:1px solid var(--dshpc-border-faint)}\\n.dshpc-dt__foot-side{display:flex;align-items:center;gap:6px}\\n.dshpc-dt__warn{font-size:11px;color:var(--dshpc-warning-label);white-space:nowrap}\\n\";\n//# sourceMappingURL=datetime-css.generated.js.map","// ⚠️ 生成物,勿手改。真源 = src/ui/marquee.css\n// 由 scripts/gen-css.mjs 生成(`pnpm run gen:css`):改样式请改那个 .css 文件后重新生成。\nexport const MARQUEE_CSS = \"/* 跑马灯(MarqueeText):双层——外层只裁剪,内层才 transform 滚动;非 hover 内层自带省略号。\\n 2026-10-20:本文件原是杂烩「select.css」(下拉 / 日历 / 时分的皮肤都装过),随着那些控件\\n 一个个删完,最后只剩跑马灯,故按本包「一个 css 服务一个对象」的格局改名归档。\\n 同批清掉的还有零引用的省略号类 .dshpc-ellipsis —— 本包三个用到截断的地方都没采纳它。 */\\n.dshpc-mq{display:block;overflow:hidden;white-space:nowrap;}\\n.dshpc-mq .dshpc-mq-in{display:inline-block;white-space:nowrap;max-width:100%;overflow:hidden;text-overflow:ellipsis;vertical-align:top;}\\n/* ⚠️ 跑法(用户 2026-10-03 拍板):**跑一遍、停在尾字**(播放 1 次 + forwards),不来回弹、不无限跑。\\n 滚距 = 精确溢出量 ⇒ 停下时最后一个字正好贴右缘,**不会跑进黑块**(黑块是旧手写版把\\n 内层盒子裁了、按「半截文本」平移导致的)。鼠标移开 ⇒ :hover 失效 ⇒ 自动复位回省略号态。 */\\n.dshpc-mq-run:hover .dshpc-mq-in{max-width:none;overflow:visible;animation:dshpc-mq-scroll var(--dshpc-mq-dur,6s) linear .4s 1 forwards;}\\n@keyframes dshpc-mq-scroll{from{transform:translateX(0)}to{transform:translateX(var(--dshpc-mq-dist,-40px))}}\\n/* 溢出渐影(用户 2026-10-24 拍板「左右稍微有点渐影」;官方口径 = dsh-client-ui-primitives@0.2.1-rc.2\\n PathLabel.module.css:13-15:mask-image 线性渐隐 + 28px 随官方)。⚠️ 只在 **hover 滚动态** 加:\\n 静态态(三个点)不要渐影(用户 2026-10-24 二次拍板),hover 滚动时两端渐影——左缘柔化被裁的文字头。 */\\n.dshpc-mq-run:hover{mask-image:linear-gradient(to right, transparent, #000 28px, #000 calc(100% - 28px), transparent);}\\n\";\n//# sourceMappingURL=marquee-css.generated.js.map","// ⚠️ 生成物,勿手改。真源 = src/ui/picker.css\n// 由 scripts/gen-css.mjs 生成(`pnpm run gen:css`):改样式请改那个 .css 文件后重新生成。\nexport const PICKER_CSS = \"\\n.dshpc-picker{position:relative;display:inline-block;font-size:13px;line-height:20px}\\n.dshpc-picker__trigger{\\n display:inline-flex;align-items:center;justify-content:space-between;gap:6px;\\n min-width:120px;max-width:100%;height:28px;padding:0 8px;\\n color:var(--dshpc-fg);background:var(--dshpc-surface-1);\\n border:1px solid var(--dshpc-border);border-radius:var(--dshpc-radius-md);cursor:pointer;\\n}\\n.dshpc-picker__trigger:disabled{color:var(--dshpc-fg-dim);cursor:not-allowed;opacity:.7}\\n/* 聚焦(键盘或点击选中)时与全站一致的蓝色描边;菜单打开后焦点会进去,触发器自然失去焦点。 */\\n.dshpc-picker__trigger:focus-visible{outline:2px solid var(--dshpc-focus);outline-offset:1px}\\n/* 文字默认靠左(吃掉剩余宽度),不给 space-between 把短文案推到中间的机会;\\n 确实要居中就显式传 align=\\\"center\\\"。 */\\n.dshpc-picker__label{flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;text-align:left}\\n.dshpc-picker__trigger--center .dshpc-picker__label{text-align:center}\\n.dshpc-picker__caret{flex:none;color:var(--dshpc-fg-3)}\\n.dshpc-picker__icon{display:inline-flex;flex:none;color:var(--dshpc-fg-2)}\\n.dshpc-picker__option-icon{display:inline-flex;flex:none;color:var(--dshpc-fg-2)}\\n.dshpc-picker__menu{\\n z-index:60;max-height:280px;overflow:auto;padding:4px;\\n /* 菜单经 FloatingPortal 挂到 body,脱离 .dshpc-picker,须显式字号,否则继承 body 的大字号 */\\n font-size:13px;line-height:20px;\\n background:var(--dshpc-surface-menu);border:1px solid var(--dshpc-border);\\n border-radius:var(--dshpc-radius-md);box-shadow:0 8px 24px rgba(15,23,42,.12);\\n}\\n/* 尺寸档(与 Field 的 sm/md/lg 对应)。 */\\n.dshpc-picker__trigger--sm{height:24px;font-size:12px}\\n.dshpc-picker__trigger--lg{height:32px}\\n/* 键盘游标所在项(无 hover 也要看得见)。 */\\n.dshpc-picker__option[data-active='true']{background:var(--dshpc-surface-sunken);outline:1px solid var(--dshpc-border)}\\n.dshpc-picker__option--clear{color:var(--dshpc-fg-3)}\\n.dshpc-picker__search{\\n width:100%;height:28px;margin-bottom:4px;padding:0 8px;box-sizing:border-box;\\n color:var(--dshpc-fg);background:var(--dshpc-surface-sunken);\\n border:1px solid var(--dshpc-border-faint);border-radius:var(--dshpc-radius-md);outline:none;\\n}\\n.dshpc-picker__group-label{\\n padding:6px 8px 2px;color:var(--dshpc-fg-3);font-size:11px;\\n}\\n.dshpc-picker__option{\\n display:flex;align-items:center;gap:6px;padding:6px 8px;border-radius:var(--dshpc-radius-sm);cursor:pointer;\\n color:var(--dshpc-fg);white-space:nowrap;\\n}\\n.dshpc-picker__option:hover{background:var(--dshpc-surface-sunken)}\\n.dshpc-picker__option--active{background:var(--dshpc-open-bg);color:var(--dshpc-business)}\\n.dshpc-picker__option--disabled{color:var(--dshpc-fg-dim);cursor:not-allowed}\\n.dshpc-picker__tick{width:12px;color:var(--dshpc-business)}\\n.dshpc-picker__empty{padding:8px;color:var(--dshpc-fg-3);text-align:center}\\n.dshpc-picker__degraded{\\n padding:6px 8px;margin-bottom:4px;border-radius:var(--dshpc-radius-sm);\\n color:var(--dshpc-warning-label);background:color-mix(in srgb,var(--dshpc-warning) 12%,transparent);\\n font-size:11px;\\n}\\n.dshpc-picker__row{display:flex;align-items:center;gap:8px}\\n\";\n//# sourceMappingURL=picker-css.generated.js.map","// ⚠️ 生成物,勿手改。真源 = src/ui/feedback.css\n// 由 scripts/gen-css.mjs 生成(`pnpm run gen:css`):改样式请改那个 .css 文件后重新生成。\nexport const FEEDBACK_CSS = \"\\n/* 遮罩 = 宿主遮罩变量 --dsw-alias-bg-mask-1(与官方 Modal / 兄弟项目 --tdt-mask 同一条真值,用户 2026-10-20)。 */\\n/* 右边界让位页面级分栏(PanelDock 发布的 --dshpc-page-inset-right,用户 2026-10-22):\\n 分栏不被压暗、照常可点;弹窗在这块**剩下**的区域里居中,就像整页被推出去一样。 */\\n.dshpc-modal-mask{\\n position:fixed;inset:0 var(--dshpc-page-inset-right,0px) 0 0;z-index:1070;\\n display:flex;align-items:center;justify-content:center;\\n background:var(--dshpc-mask);\\n}\\n/* 大弹窗家族(md/lg):抄兄弟项目 archive-session-css 的 .dsh-tdt-sv-panel(surface-base + border-l2 + radius 12 + shadow-2)。 */\\n.dshpc-modal{\\n display:flex;flex-direction:column;box-sizing:border-box;\\n background:var(--dshpc-surface-base);color:var(--dshpc-fg);\\n border:1px solid var(--dshpc-border);border-radius:var(--dshpc-radius-md);\\n box-shadow:var(--dshpc-shadow-2);overflow:hidden;\\n}\\n.dshpc-modal__head{\\n display:flex;align-items:center;gap:8px;padding:18px 31px 12px;\\n border-bottom:1px solid var(--dshpc-border);flex-wrap:wrap;\\n}\\n/* 标题组:第一行 = 标题 + 右侧小块(徽标紧跟标题),第二行 = 副标题。 */\\n.dshpc-modal__titlegroup{display:flex;flex-direction:column;gap:2px;min-width:0;flex:0 1 auto}\\n.dshpc-modal__titlerow{display:flex;align-items:center;gap:8px;min-width:0}\\n.dshpc-modal__title{font-size:var(--dshpc-font-lg);font-weight:600;line-height:1.4;min-width:0}\\n/* 标题下副标题行(兄弟项目 .dsh-tdt-sv-sid:等宽字体、caption 色、可换行)。 */\\n.dshpc-modal__sid{font-family:var(--ds-font-family-code,monospace);font-size:var(--dshpc-font-xs);color:var(--dshpc-fg-3);word-break:break-all}\\n/* 关闭按钮:24×24 方角图标位,不借用 Picker 的触发器皮肤(那份带 min-width:120px)。 */\\n.dshpc-modal__close{\\n display:inline-flex;align-items:center;justify-content:center;flex:none;\\n width:20px;height:20px;padding:0;border:none;border-radius:var(--dshpc-radius-sm);\\n background:transparent;color:var(--dshpc-fg-3);font-family:inherit;font-size:13px;line-height:1;cursor:pointer;\\n transition:background-color var(--dshpc-dur-fast) var(--dshpc-ease),color var(--dshpc-dur-fast) var(--dshpc-ease);\\n}\\n.dshpc-modal__close:hover{background:var(--dshpc-hover);color:var(--dshpc-fg)}\\n.dshpc-modal__close:focus-visible{outline:2px solid var(--dshpc-focus);outline-offset:1px}\\n/* body = 唯一滚动容器:内距与滚动都归它(滚动条贴面板右缘,不被内距挤进来);\\n 内容按流排,不设 height:100%、不自己开滚动条。 */\\n.dshpc-modal__body{flex:1 1 auto;min-height:0;overflow:auto;padding:17px 31px}\\n.dshpc-modal__foot{display:flex;justify-content:flex-end;gap:8px;padding:12px 31px 18px}\\n.dshpc-toast-host{\\n position:fixed;z-index:1090;left:50%;bottom:32px;transform:translateX(-50%);\\n display:flex;flex-direction:column;gap:8px;align-items:center;pointer-events:none;\\n}\\n.dshpc-toast{\\n padding:8px 14px;border-radius:8px;font-size:13px;color:var(--dshpc-fg);\\n background:var(--dshpc-surface-menu);border:1px solid var(--dshpc-border);\\n box-shadow:0 8px 24px rgba(15,23,42,.16);\\n}\\n.dshpc-toast--success{color:var(--dshpc-success);border-color:color-mix(in srgb,var(--dshpc-success) 40%,transparent)}\\n.dshpc-toast--error{color:var(--dshpc-danger);border-color:color-mix(in srgb,var(--dshpc-danger) 40%,transparent)}\\n.dshpc-error__retry{\\n margin-top:8px;color:var(--dshpc-link);cursor:pointer;background:none;border:none;padding:0;\\n}\\n/* 原生弹窗演示:经宿主 Modal 的 contentClassName 注入,证明宿主内容区尺寸可经类名自定义。 */\\n.dshpc-native-demo-content{max-width:520px}\\n/* Modal 头部四槽:左图标 / 标题组 / 弹性间隔 / 右侧动作区 + 关闭钮。 */\\n.dshpc-modal__heading{display:flex;align-items:center;gap:8px;min-width:0;flex:0 1 auto}\\n.dshpc-modal__lead{flex:none;display:inline-flex;align-items:center;justify-content:center;font-size:16px;line-height:1}\\n.dshpc-modal__extra{flex:none;display:inline-flex;align-items:center}\\n.dshpc-modal__spacer{flex:1 1 auto;min-width:8px}\\n.dshpc-modal__actions{flex:none;display:flex;align-items:center;gap:8px}\\n/* 头部信号图标(AlertModal 按 severity 注入):自含配色,不依赖宿主 token。 */\\n.dshpc-alert-sev{display:inline-flex;align-items:center;justify-content:center;width:20px;height:20px;border-radius:50%;font-size:12px;color:#fff;flex:none}\\n.dshpc-alert-sev--info{background:#2563eb}\\n.dshpc-alert-sev--success{background:#16a34a}\\n.dshpc-alert-sev--warning{background:#d97706}\\n.dshpc-alert-sev--error{background:#dc2626}\\n/* 小确认框家族(sm):严格抄兄弟项目 renderConfirm 的 dialogStyle(task-list.tsx:456)——\\n 360px 宽 / 18px 内距 / 头部无分隔线 / 说明文字 fg-2 / 底部按钮右对齐。 */\\n.dshpc-modal--sm{padding:18px}\\n.dshpc-modal--sm .dshpc-modal__head{padding:0 0 8px;border-bottom:none}\\n.dshpc-modal--sm .dshpc-modal__body{padding:0 0 14px;overflow:visible;font-size:var(--dshpc-font-sm);color:var(--dshpc-fg-2);line-height:var(--dshpc-line-sm)}\\n.dshpc-modal--sm .dshpc-modal__foot{padding:0}\\n\";\n//# sourceMappingURL=feedback-css.generated.js.map","// ⚠️ 生成物,勿手改。真源 = src/ui/card.css\n// 由 scripts/gen-css.mjs 生成(`pnpm run gen:css`):改样式请改那个 .css 文件后重新生成。\nexport const CARD_CSS = \"\\n.dshpc-card{\\n position:relative;box-sizing:border-box;color:var(--dshpc-fg);font:inherit;text-align:left;\\n --card-accent:var(--dshpc-business);\\n --card-accent-soft:var(--dshpc-business-soft);\\n}\\n/* 档位 → token(照 records-timeline 的 tone 模式:一个变量切档,不写 5 套规则;浅底与色条同源)。 */\\n.dshpc-card--success{--card-accent:var(--dshpc-success);--card-accent-soft:var(--dshpc-success-soft)}\\n.dshpc-card--warning{--card-accent:var(--dshpc-warning);--card-accent-soft:var(--dshpc-warning-soft)}\\n.dshpc-card--danger{--card-accent:var(--dshpc-danger);--card-accent-soft:var(--dshpc-danger-soft)}\\n/* neutral 浅底借 chip 底(兄弟项目 mute 档同款:明暗都成立)。 */\\n.dshpc-card--neutral{--card-accent:var(--dshpc-fg-4);--card-accent-soft:var(--dshpc-chip-bg)}\\n\\n/* 头部一行 = 色条 + 主内容 + 右侧槽,**整体垂直居中**:调用方在 action 里裸放一个元素\\n (按钮 / 文字 / 图标)不用自己套容器居中;一行两行、右边怎么放由调用方在框内自定。 */\\n.dshpc-card__head{display:flex;align-items:center;gap:8px;min-width:0}\\n.dshpc-card__main{flex:1;min-width:0}\\n.dshpc-card__side{display:flex;align-items:center;gap:6px;flex:none}\\n\\n/* ── 外观一 · StripCard:同色系浅底 + 1px 不可见占位边框 + 方角 + 4px 通高方角色条贴左缘 ── */\\n.dshpc-card--strip{\\n padding:12px 12px 12px 20px;border:1px solid transparent;\\n background:var(--card-accent-soft,transparent);\\n}\\n/* 左内边距 20px = 16 留白 + 4 条宽 ⇒ 内容从色条右缘起算;色条绝对定位通高,跟着内容高度自适应。 */\\n.dshpc-card--strip .dshpc-card__bar{position:absolute;left:0;top:0;bottom:0;width:4px;background:var(--card-accent)}\\n\\n/* ── 外观二 · Card:surface 底 + 1px 实色边框 + 圆角 + 行内圆角短条 ── */\\n.dshpc-card--bordered{\\n /* 左内边距 12(比上/右/下 14 少 2):竖条贴近边框;头部内缩 2px ⇒ 主内容跟着左移 2px,\\n 竖条↔内容的 12px 间距不变——比「条子 left:-2 而内容不动」更正规(不靠相对定位硬补)。 */\\n padding:14px 14px 14px 12px;border:1px solid var(--dshpc-border);border-radius:var(--dshpc-radius-sm);\\n background:var(--dshpc-surface-1);\\n}\\n.dshpc-card--bordered .dshpc-card__head{gap:12px}\\n/* 短条:行内 flex 项,**高度跟着内容走**(stretch),最小一行文字(--dshpc-line-md)——\\n 一行文字时条子与文字齐高,不会把卡撑高;竖条距左 12(= 左内边距),距上/右/下 14。 */\\n.dshpc-card--bordered .dshpc-card__bar{width:6px;flex:none;align-self:stretch;min-height:var(--dshpc-line-md);border-radius:var(--dshpc-radius-xs);background:var(--card-accent)}\\n.dshpc-card__toggle{\\n display:inline-flex;align-items:center;justify-content:center;\\n width:24px;height:24px;padding:0;background:none;border:none;border-radius:6px;\\n color:var(--dshpc-fg-3);cursor:pointer;\\n}\\n.dshpc-card__toggle:hover{background:var(--dshpc-surface-sunken);color:var(--dshpc-fg)}\\n.dshpc-card__caret{display:inline-block;font-size:10px;transition:transform .15s ease}\\n.dshpc-card__caret.is-open{transform:rotate(180deg)}\\n.dshpc-card__panel{margin-top:8px;padding-top:8px;border-top:1px solid var(--dshpc-border-faint)}\\n\";\n//# sourceMappingURL=card-css.generated.js.map","// ⚠️ 生成物,勿手改。真源 = src/ui/chip.css\n// 由 scripts/gen-css.mjs 生成(`pnpm run gen:css`):改样式请改那个 .css 文件后重新生成。\nexport const CHIP_CSS = \"\\n/* 三条局部变量承载配色:neutral 走旧灰面;语义档换底字配对(2026-10-20 用户要多色多尺寸标签)。 */\\n.dshpc-chip{--chip-bg:var(--dshpc-chip-bg);--chip-fg:var(--dshpc-fg);--chip-bg-hover:var(--dshpc-chip-bg-hover);\\n display:inline-flex;align-items:center;justify-content:center;gap:4px;padding:1px 8px;\\n box-sizing:border-box;border-radius:var(--dshpc-radius-pill,999px);border:none;\\n background:var(--chip-bg);color:var(--chip-fg);\\n font-family:inherit;font-size:11px;line-height:18px;margin:0;\\n /* 2026-10-18:chip 是 flex 行里的常用项,禁止被压缩换行(预览站出现过文字竖排、互相叠压的挤压)。 */\\n white-space:nowrap;flex:none;\\n appearance:none;-webkit-appearance:none;\\n}\\n/* md 档:卡片元信息行等稍大场景;sm 即旧版默认,逐像素不动。 */\\n.dshpc-chip--md{padding:2px 10px;font-size:12px;line-height:20px;}\\n/* xs 档:标题后缀等极紧凑场景(2026-10-20 用户要更小标签);16px 高、font 10。 */\\n.dshpc-chip--xs{padding:0 6px;font-size:10px;line-height:16px;}\\n/* 语义色实心档:底 / 字 / hover 配对与 Button 同源(黄底中高明度 ⇒ 字用 --dshpc-on-warning)。 */\\n.dshpc-chip--business{--chip-bg:var(--dshpc-business);--chip-fg:var(--dshpc-on-signal);--chip-bg-hover:var(--dshpc-business-hover);}\\n.dshpc-chip--success{--chip-bg:var(--dshpc-success);--chip-fg:var(--dshpc-on-signal);--chip-bg-hover:var(--dshpc-success-hover);}\\n.dshpc-chip--warning{--chip-bg:var(--dshpc-warning);--chip-fg:var(--dshpc-on-warning);--chip-bg-hover:var(--dshpc-warning-hover);}\\n.dshpc-chip--danger{--chip-bg:var(--dshpc-danger);--chip-fg:var(--dshpc-on-signal);--chip-bg-hover:var(--dshpc-danger-hover);}\\n/* 可点态:button 渲染(见 Chip.ts),光标 + hover 加深。 */\\n.dshpc-chip--clickable{cursor:pointer;transition:background-color var(--dshpc-dur-fast) var(--dshpc-ease);}\\n.dshpc-chip--clickable:hover:not(:disabled){background:var(--chip-bg-hover)}\\n.dshpc-chip:focus-visible{outline:2px solid var(--dshpc-focus);outline-offset:1px}\\n.dshpc-chip:disabled{cursor:default;color:var(--dshpc-fg-3)}\\n@media (prefers-reduced-motion: reduce){.dshpc-chip{transition:none}}\\n\";\n//# sourceMappingURL=chip-css.generated.js.map","// ⚠️ 生成物,勿手改。真源 = src/ui/code-viewer.css\n// 由 scripts/gen-css.mjs 生成(`pnpm run gen:css`):改样式请改那个 .css 文件后重新生成。\nexport const CODE_VIEWER_CSS = \"/* CodeViewer(只读 CodeMirror 查看器)样式。类名固定 dshpc-cv*;颜色吃 --dshpc-* token,\\n 深色由 design 的 token 深色段自动生效(不写死颜色值)。 */\\n.dshpc-cv{position:relative;display:flex;flex-direction:column;height:100%;min-height:0;}\\n.dshpc-cv__copy{position:absolute;top:6px;right:6px;z-index:5;display:inline-flex;align-items:center;justify-content:center;width:28px;height:28px;padding:0;appearance:none;border:1px solid var(--dshpc-border,rgba(128,128,128,.35));border-radius:var(--dshpc-radius-sm,6px);background:var(--dshpc-surface-1,#fff);color:var(--dshpc-fg-2,rgba(128,128,128,.95));cursor:pointer;opacity:0;transition:opacity .12s var(--dshpc-ease,ease),background .12s,color .12s;}\\n.dshpc-cv:hover .dshpc-cv__copy,.dshpc-cv__copy:focus-visible{opacity:1;}\\n.dshpc-cv__copy:hover{background:var(--dshpc-hover,rgba(38,49,72,.06));color:var(--dshpc-fg,#1f2328);}\\n.dshpc-cv__copy svg{width:16px;height:16px;}\\n.dshpc-cv__editor{flex:1 1 auto;min-height:0;overflow:hidden;}\\n.dshpc-cv__editor .cm-editor{height:100%;}\\n.dshpc-cv__editor .cm-scroller{overflow:auto;}\\n\";\n//# sourceMappingURL=code-viewer-css.generated.js.map","// ⚠️ 生成物,勿手改。真源 = src/ui/panel-dock.css\n// 由 scripts/gen-css.mjs 生成(`pnpm run gen:css`):改样式请改那个 .css 文件后重新生成。\nexport const PANEL_DOCK_CSS = \"\\n/* 停靠栏 = **布局成员**,不是浮层:它占宽度、把主区真正挤窄(兄弟项目 2026-09-28:\\n 「分栏压过来,不是盖上去」)。所以调用方必须把它放进自己的 flex 根里。 */\\n.dshpc-dock{display:flex;flex:0 0 auto;align-self:stretch;min-width:0}\\n\\n/* 单栏:sticky + 100vh 让它在页面滚动时保持可见,同时仍然占宽度。\\n ⚠️ **本条刻意不设 z-index**:布局成员一旦带正 z-index,就会无条件压过宿主 portal 到 body 的\\n 弹窗(兄弟项目 2026-10-05 真机事故「侧边栏盖住宿主设置弹窗」)。层序交给 DOM 顺序裁决。 */\\n.dshpc-dock__panel{\\n box-sizing:border-box;position:sticky;top:0;align-self:stretch;\\n display:flex;flex-direction:column;flex:0 0 auto;\\n /* 高度默认视口高(整页场景);嵌在定高容器里时由调用方给 --dshpc-dock-h(如 420px / 100%)。 */\\n height:var(--dshpc-dock-h,100vh);max-height:var(--dshpc-dock-h,100vh);min-width:0;\\n background:var(--dshpc-surface-base);color:var(--dshpc-fg);\\n border-left:1px solid var(--dshpc-border);\\n box-shadow:var(--dshpc-shadow-2);\\n}\\n\\n.dshpc-dock__head{\\n flex:none;display:flex;align-items:center;gap:8px;\\n /* 右侧 34px = 8(边距) + 20(关钮) + 6(呼吸):给绝对定位的关钮留位,标题/extra 不从它底下钻 */\\n padding:10px 34px 10px 14px;\\n border-bottom:1px solid var(--dshpc-border-faint);\\n}\\n/* 图标位 / 标题右侧的内容位:消费方传 ReactNode,可塞多个;库只负责排布,不抢宽度。 */\\n.dshpc-dock__lead{display:inline-flex;align-items:center;gap:6px;flex:none;color:var(--dshpc-fg-2)}\\n.dshpc-dock__extra{display:inline-flex;align-items:center;gap:6px;flex:none;margin-left:auto}\\n/* 自定义头部:整行归调用方 —— 不加内边距/边框/背景,也不给关钮留内联空间(关钮是绝对定位的)。 */\\n.dshpc-dock__head--custom{display:block;padding:0;border-bottom:none}\\n.dshpc-dock__title{\\n flex:1 1 auto;min-width:0;\\n overflow:hidden;text-overflow:ellipsis;white-space:nowrap;\\n font-size:var(--dshpc-font-md);font-weight:600;\\n}\\n/* 关闭钮:20×20 方角图标位(与 Modal 的关闭钮同规格,不借 Picker 触发器皮肤)。 */\\n.dshpc-dock__close{\\n display:inline-flex;align-items:center;justify-content:center;flex:none;\\n width:20px;height:20px;padding:0;border:none;border-radius:var(--dshpc-radius-sm);\\n background:transparent;color:var(--dshpc-fg-3);\\n font-family:inherit;font-size:13px;line-height:1;cursor:pointer;\\n transition:background-color var(--dshpc-dur-fast) var(--dshpc-ease),color var(--dshpc-dur-fast) var(--dshpc-ease);\\n}\\n.dshpc-dock__close:hover{background:var(--dshpc-hover);color:var(--dshpc-fg)}\\n.dshpc-dock__close:focus-visible{outline:2px solid var(--dshpc-focus);outline-offset:1px}\\n/* 头部关钮:绝对定位,位置与内置头完全一致(top 10 / right 8);自定义头也用这一个位置。\\n 锚点是面板本身(position:sticky 即定位上下文),不在滚动内容里,所以正文滚动它不跟滚。 */\\n.dshpc-dock__close--abs{position:absolute;top:10px;right:8px;z-index:8}\\n/* 浮动关钮:无头部面板用,略收一点边距。 */\\n.dshpc-dock__close--floating{\\n position:absolute;top:6px;right:6px;z-index:8;\\n background:var(--dshpc-surface-menu);border:1px solid var(--dshpc-border-faint);\\n}\\n\\n/* 内容区自己滚:面板高度锁 100vh,内容不设内部滚动就会把整页撑高。 */\\n.dshpc-dock__body{flex:1 1 auto;min-height:0;overflow:auto}\\n\\n/* 拖拽条:左缘 6px 命中区,**不画线**,hover/按住时才浮出一条浅色带。\\n z-index 7 必须高于面板内容里的浮层(复制钮一类),否则命中区会被内容盖住。 */\\n.dshpc-dock__resizer{\\n position:absolute;left:0;top:0;bottom:0;width:6px;\\n z-index:7;cursor:col-resize;background:transparent;\\n transition:background-color var(--dshpc-dur-fast) var(--dshpc-ease);\\n}\\n/* hover/按住:不填灰带,改为官方 work 区指示条样式 —— 左缘 2px 蓝竖条、上下渐隐\\n (颜色走 business 蓝的官方 alias,明暗自动跟随宿主;命中区仍是 6px 不变)。 */\\n.dshpc-dock__resizer:hover,.dshpc-dock__resizer:active{\\n background:linear-gradient(180deg,transparent,var(--dshpc-business) 30%,var(--dshpc-business) 70%,transparent) left center / 1px 100% no-repeat;\\n}\\n\\n/* 拖动期:① <iframe>(PDF / HTML 预览)是独立文档,会吞掉父文档的 pointermove,\\n 向右拖进 iframe 就卡死 —— 整片让出指针事件;② contain 把重排隔离在栏内,\\n 否则每帧改宽度都会牵动整页重排(兄弟项目 2026-10-04 真机「挪很久才动一下」)。 */\\n.dshpc-dock.dshpc-dock--resizing iframe{pointer-events:none}\\n.dshpc-dock.dshpc-dock--resizing .dshpc-dock__panel{contain:layout paint;will-change:width}\\n\";\n//# sourceMappingURL=panel-dock-css.generated.js.map","// ⚠️ 生成物,勿手改。真源 = src/explorer/explorer.css\n// 由 scripts/gen-css.mjs 生成(`pnpm run gen:css`):改样式请改那个 .css 文件后重新生成。\nexport const EXPLORER_CSS = \"/* 工作区文件浏览器(dshpc-fb-*)。\\n *\\n * 度量真源 = 兄弟项目 dsh-task-dispatch-table 的 src/client/archive-session-css.ts\\n * (.dsh-tdt-sv-* 全族)。**逐条照抄,不许自己估**:padding / gap / 圆角 / 字号 / 行高 /\\n * 边框色 / 悬停色 / 透明度动画 / 溢出策略,一一对应,改这里之前先去那边对原文。\\n * 前缀与变量名换成本仓口径(--tdt-* → --dshpc-*),数值不换。\\n *\\n * 控件:能核心就核心(面包屑 = Button ghost、行尾 = Button outline、展开 / 图标 = IconButton、\\n * 分段 = Segmented、文字 = MarqueeText)。核心控件自带的 padding / 高度 / 皮肤在本文件里\\n * **按兄弟数值覆盖**(选择器带 .dshpc-fb 前缀提高特异性,确保盖得住控件默认值)。\\n */\\n.dshpc-fb{\\n position:relative;display:flex;flex-direction:column;height:100%;min-height:0;\\n background:var(--dshpc-surface-base);color:var(--dshpc-fg);\\n}\\n\\n/* 第一排:▾ 选层 + 面包屑 + 动作(兄弟 .dsh-tdt-sv-crumbbar)\\n ⚠️ 不能 overflow:hidden —— 下拉浮层挂在它下面,裁了就看不见。 */\\n.dshpc-fb__bar{\\n position:relative;flex:none;display:flex;align-items:center;gap:2px;\\n padding:4px 10px;border-bottom:1px solid var(--dshpc-border);white-space:nowrap;\\n}\\n.dshpc-fb__menu-wrap{position:relative;flex:none;display:inline-flex}\\n.dshpc-fb__crumbs{position:relative;flex:1;min-width:0;display:flex;align-items:center;gap:2px;overflow:hidden}\\n.dshpc-fb__crumbs-measure{\\n position:absolute;top:0;left:0;display:inline-flex;align-items:center;gap:2px;\\n visibility:hidden;pointer-events:none;white-space:nowrap;\\n}\\n\\n/* 面包屑:核心 ghost 钮,但皮肤与尺寸取兄弟 .dsh-tdt-sv-crumb(高由内容决定,不锁控制高)。 */\\n.dshpc-fb .dshpc-fb__crumb{\\n appearance:none;background:0 0;border:none;height:auto;\\n padding:2px 4px;border-radius:var(--dshpc-radius-sm);\\n font:inherit;font-size:var(--dshpc-font-sm);line-height:var(--dshpc-line-sm);\\n color:var(--dshpc-fg-2);cursor:pointer;\\n display:inline-flex;align-items:center;min-width:0;overflow:hidden;text-overflow:ellipsis;\\n}\\n.dshpc-fb .dshpc-fb__crumb:hover{background:var(--dshpc-hover);color:var(--dshpc-fg)}\\n.dshpc-fb .dshpc-fb__crumb:disabled{color:var(--dshpc-fg-2);cursor:default}\\n.dshpc-fb .dshpc-fb__crumb--current{cursor:default;color:var(--dshpc-fg);font-weight:600;min-width:0}\\n.dshpc-fb .dshpc-fb__crumb--current:hover{background:0 0}\\n.dshpc-fb__crumb-mq{flex:1 1 auto;min-width:0}\\n.dshpc-fb__crumb-sep{flex:none;color:var(--dshpc-fg-3)}\\n\\n/* 越界(outside-workspace)第一排:只读完整路径(兄弟 .dsh-tdt-sv-crumbbar-plain-inner)。 */\\n.dshpc-fb__bar-plain{\\n font-family:var(--dshpc-font-mono,ui-monospace,SFMono-Regular,Menlo,Consolas,monospace);\\n font-size:var(--dshpc-font-sm);line-height:var(--dshpc-line-sm);color:var(--dshpc-fg-2);\\n white-space:nowrap;overflow:hidden;text-overflow:ellipsis;cursor:default;user-select:none;\\n}\\n.dshpc-fb__actions{flex:none;display:flex;align-items:center;gap:4px}\\n\\n/* ▾ 选层浮层(兄弟 .dsh-tdt-sv-crumbs-*)。\\n 层序:兄弟是 30/31;本仓 picker 面板是 1100,遮罩必须高于它,否则菜单开着点面板不算「点外部」。 */\\n.dshpc-fb__crumbs-backdrop{position:fixed;inset:0;z-index:1200;background:transparent}\\n.dshpc-fb__crumbs-menu{\\n position:absolute;top:calc(100% + 4px);left:0;z-index:1201;min-width:160px;max-height:240px;overflow:auto;\\n background:var(--dshpc-surface-menu);border:1px solid var(--dshpc-border);border-radius:var(--dshpc-radius-sm);\\n box-shadow:0 4px 16px rgba(0,0,0,.18);padding:4px;display:flex;flex-direction:column;\\n}\\n.dshpc-fb__menu-item{\\n appearance:none;background:0 0;border:none;text-align:left;font:inherit;\\n font-size:var(--dshpc-font-sm);line-height:var(--dshpc-line-md);\\n padding:4px 8px;border-radius:var(--dshpc-radius-sm);color:var(--dshpc-fg);cursor:pointer;\\n max-width:280px;display:flex;align-items:center;gap:2px;\\n overflow:hidden;text-overflow:ellipsis;white-space:nowrap;\\n}\\n.dshpc-fb__menu-item:hover{background:var(--dshpc-hover)}\\n.dshpc-fb__menu-empty{\\n font-size:var(--dshpc-font-sm);line-height:var(--dshpc-line-md);padding:4px 8px;color:var(--dshpc-fg-3);\\n}\\n.dshpc-fb__menu-icon{flex:none;display:inline-flex}\\n.dshpc-fb__menu-chev{flex:none;color:var(--dshpc-fg-3);margin-right:1px}\\n.dshpc-fb__menu-chev-slot{flex:none;width:11px;height:11px;margin-right:1px}\\n.dshpc-fb__menu-label{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}\\n\\n/* 第二排(仅预览态):文件名 + 工具(兄弟 .dsh-tdt-sv-titlebar / -preview-title-inner)。 */\\n.dshpc-fb__title{\\n flex:none;display:flex;align-items:center;gap:8px;\\n padding:8px 14px;border-bottom:1px solid var(--dshpc-border);\\n}\\n.dshpc-fb__title-inner{\\n font-family:var(--dshpc-font-mono,ui-monospace,SFMono-Regular,Menlo,Consolas,monospace);\\n font-size:var(--dshpc-font-sm);line-height:var(--dshpc-line-sm);color:var(--dshpc-fg);\\n white-space:nowrap;overflow:hidden;text-overflow:ellipsis;cursor:default;\\n}\\n\\n/* 主体(兄弟 .dsh-tdt-sv-preview-body / -hint / -preview-err) */\\n.dshpc-fb__body{flex:1;min-height:0;overflow-x:hidden;overflow-y:auto;padding:12px 14px}\\n.dshpc-fb__note{font-size:var(--dshpc-font-sm);color:var(--dshpc-fg-2);text-align:center;padding:12px 0}\\n.dshpc-fb__err{\\n display:flex;flex-direction:column;align-items:flex-start;gap:10px;\\n font-size:var(--dshpc-font-sm);line-height:1.6;color:var(--dshpc-fg-2);padding:8px 0;\\n}\\n\\n/* 目录树(兄弟 .dsh-tdt-sv-tree*) */\\n.dshpc-fb__tree{flex:1;min-height:0;overflow:auto;padding:6px 8px}\\n.dshpc-fb__row{\\n display:flex;align-items:center;gap:8px;padding:6px 8px;\\n border-radius:var(--dshpc-radius-sm);cursor:pointer;user-select:none;\\n}\\n.dshpc-fb__row:hover{background:var(--dshpc-hover)}\\n.dshpc-fb__row:focus-visible{outline:2px solid var(--dshpc-focus);outline-offset:-2px}\\n.dshpc-fb__row-icon{flex:none;display:inline-flex;color:var(--dshpc-fg-2)}\\n.dshpc-fb__row-name{\\n flex:1;min-width:0;font-size:var(--dshpc-font-md);line-height:var(--dshpc-line-md);color:var(--dshpc-fg);\\n overflow:hidden;text-overflow:ellipsis;white-space:nowrap;\\n}\\n\\n/* 展开开关:核心 IconButton,命中位 20×20 + 展开时转 90°(兄弟 .dsh-tdt-sv-tree-toggle{,-open})。 */\\n.dshpc-fb .dshpc-fb__row-toggle{\\n appearance:none;background:0 0;border:none;flex:none;\\n width:20px;height:20px;padding:0;margin:0;border-radius:var(--dshpc-radius-sm);\\n color:var(--dshpc-fg-2);cursor:pointer;\\n display:inline-flex;align-items:center;justify-content:center;\\n transition:transform var(--dshpc-dur-fast) var(--dshpc-ease),background var(--dshpc-dur-fast) var(--dshpc-ease);\\n}\\n.dshpc-fb .dshpc-fb__row-toggle--open{transform:rotate(90deg)}\\n\\n/* 行尾「进入 / 选择」:核心 outline 钮,皮肤取兄弟 .dsh-tdt-sv-tree-act(高由内容决定)。\\n 平时隐身但占位(opacity 而非 display)⇒ 出现时不顶动行内布局。 */\\n.dshpc-fb .dshpc-fb__row-act{\\n flex:none;margin-left:auto;appearance:none;background:0 0;\\n border:1px solid var(--dshpc-border);border-radius:var(--dshpc-radius-sm);\\n height:auto;padding:2px 8px;font-size:var(--dshpc-font-sm);line-height:1.4;\\n color:var(--dshpc-fg-2);cursor:pointer;\\n opacity:0;pointer-events:none;\\n transition:opacity var(--dshpc-dur-fast) var(--dshpc-ease);\\n}\\n.dshpc-fb__row:hover .dshpc-fb__row-act,.dshpc-fb .dshpc-fb__row-act:focus-visible{opacity:1;pointer-events:auto}\\n.dshpc-fb .dshpc-fb__row-act:hover{background:var(--dshpc-hover);color:var(--dshpc-fg)}\\n\\n.dshpc-fb__row-children{\\n margin-left:9px;padding-left:7px;border-left:1px solid var(--dshpc-border);\\n display:flex;flex-direction:column;\\n}\\n.dshpc-fb__row-note{flex:none;padding:8px 10px;font-size:var(--dshpc-font-sm);color:var(--dshpc-fg-3)}\\n.dshpc-fb__row-err{padding:4px 8px 4px 36px;font-size:var(--dshpc-font-sm);color:var(--dshpc-danger)}\\n\\n/* 预览体内部容器(仅本仓预览组件用;兄弟对应 preview-fill / preview-body-code 一类)。\\n 必须 border-box:渲染态 inline 加了 padding:12px 14px,content-box 下 width:100%+padding\\n 会溢出父层 28px(父 .dshpc-fb 无 overflow 裁切)→ 恒多一条横滚条;border-box 把 padding\\n 算进 100%,从根消除该溢出。 */\\n.dshpc-fb__text{flex:1;min-height:0;overflow:auto;width:100%;box-sizing:border-box}\\n.dshpc-fb__banner{padding:6px 10px;background:var(--dshpc-open-bg);color:var(--dshpc-fg-2);font-size:var(--dshpc-font-sm)}\\n.dshpc-fb__more{display:flex;justify-content:center;padding:10px}\\n.dshpc-fb__image{max-width:100%;border-radius:var(--dshpc-radius-sm);border:1px solid var(--dshpc-border)}\\n/* iframe 的外壳(兄弟 .dsh-tdt-sv-preview-fill):iframe 必须包在这一层里才拿得到高度——\\n 裸挂 iframe 时替换元素的自动最小尺寸会让高度算不出来(表现为预览区整片空白、像没反应)。 */\\n.dshpc-fb__fill{flex:1;min-height:0;display:flex;overflow:hidden;padding:0}\\n.dshpc-fb__frame{flex:1;min-height:0;width:100%;height:100%;border:none;background:var(--dshpc-surface-1)}\\n\";\n//# sourceMappingURL=explorer-css.generated.js.map","// ⚠️ 生成物,勿手改。真源 = src/session/session.css\n// 由 scripts/gen-css.mjs 生成(`pnpm run gen:css`):改样式请改那个 .css 文件后重新生成。\nexport const SESSION_CSS = \"/* 会话预览(SessionViewModal)自绘样式:只装本包自己的组件(暂存输入区 / fork / 探针等)\\n + 两个稳定钩子类(dshpc-sv-frame / dshpc-sv-scroll)。\\n 已删:ChangedFiles 卡与 FileDiff 的全部自绘规则(2026-10-24)——官方 ChangedFiles /\\n FileDiff 模块类由 officialClass() 运行时发现并挂在元素上,本包不再有一行兜底。\\n ⚠️ 2026-10-23 起不再有官方类兜底:镜像官方组件的元素一律挂官方 CSS-module 类名\\n (officialClass() 运行时发现,取不到 = 空类、裸结构不白屏)——本包只跑 DSH 宿主、官方样式必在场,\\n 自绘一一对应是死代码。要改官方观感走 token 覆盖 / 双类名钩子(见 ChatView.ts 头注),别在这加兜底。\\n 类名固定 dshpc-sv-*;颜色一律走 --dshpc-* token(明暗自适应)。\\n 外壳(遮罩 / 面板 / 头部 / 关闭钮)= 核心 Modal(size lg)。 */\\n/* 会话区 = 普通纵向流:不设高度、不自己滚(滚动与内距归核心 Modal body,用户 2026-10-22 口径)。 */\\n.dshpc-sv{display:flex;flex-direction:column;min-width:0;gap:10px}\\n\\n/* 官方样式未命中时的可见探针(挂在头部副标题行,不占正文)。 */\\n.dshpc-sv-probe{font-size:var(--dshpc-font-xs);color:var(--dshpc-warning,#b7791f)}\\n\\n/* 头部归档标识(官方归档图标 + 「已归档」)。 */\\n.dshpc-sv-archived{display:inline-flex;align-items:center;gap:4px;font-size:var(--dshpc-font-xs);font-weight:400;color:var(--dshpc-fg-3)}\\n\\n/* 内距与滚动全部让给核心 Modal body ⇒ 这里把官方 ChatView.frame / scroll 的内距、\\n overflow、高度一律归零(双类名 0,2,0 压过 CSS module,不靠注入顺序)。\\n ⚠️ 必须同时把 flex 收掉:官方 scroll 是 flex:1(basis=0),在**自动高**的容器里会把\\n 会话区压成 0 高 —— 这正是「内容自管高度」的老毛病,别再放回来。 */\\n.dshpc-sv-frame.dshpc-sv-frame{padding-top:0;padding-bottom:0;}\\n\\n.dshpc-sv-scroll.dshpc-sv-scroll{padding:0;overflow:visible;height:auto;max-height:none;flex:none;}\\n\\n/* 会话区保底:高度由内容决定(撑开由 Modal body 滚)。 */\\n.dshpc-sv-chat{flex:none;min-height:0;}\\n\\n\\n.dshpc-sv-assistant{align-self:stretch;font-size:var(--dshpc-font-lg);line-height:1.7;word-break:break-word;}\\n\\n.dshpc-sv-image{align-self:flex-start;font-size:var(--dshpc-font-sm);color:var(--dshpc-fg-3,rgba(128,128,128,.8));border:1px dashed var(--dshpc-border,rgba(128,128,128,.35));border-radius:var(--dshpc-radius-sm);padding:4px 10px;}\\n\\n/* 工具卡根(SessionViewModal legacy 兜底渲染直接用;正常 keyed 路径一律挂官方 ToolRow 类)。 */\\n.dshpc-sv-tool{flex-direction:column;display:flex;}\\n\\n.dshpc-sv-notice{align-self:center;font-size:var(--dshpc-font-sm);color:var(--dshpc-fg-3,rgba(128,128,128,.8));padding:2px 8px;}\\n\\n\\n.dshpc-sv-forkerr{margin:0;font-size:var(--dshpc-font-lg);line-height:var(--dshpc-line-lg);color:var(--dshpc-danger,#e5484d);word-break:break-word;}\\n\\n.dshpc-sv-forktext{margin:0;font-size:var(--dshpc-font-sm);line-height:var(--dshpc-line-sm);color:var(--dshpc-fg-2);}\\n\\n/* ── 暂存输入区(期4:打字 → 确定 → fork 带话跳官方视图)── */\\n.dshpc-sv-composer{flex:1;display:flex;align-items:flex-end;gap:8px;flex-wrap:wrap;}\\n\\n.dshpc-sv-composer textarea{flex:1;min-width:0;resize:none;font:inherit;font-size:var(--dshpc-font-lg);line-height:var(--dshpc-line-lg);color:var(--dshpc-fg,#1f2328);background:var(--dshpc-surface-2,rgba(128,128,128,.10));border:1px solid var(--dshpc-border,rgba(128,128,128,.28));border-radius:var(--dshpc-radius-md);padding:8px 12px;min-height:40px;max-height:120px;}\\n\\n.dshpc-sv-composer textarea:focus-visible{outline:2px solid var(--dshpc-focus,#3b5bdb);outline-offset:-1px;}\\n\\n.dshpc-sv-composer-hint{flex:none;font-size:var(--dshpc-font-xs);color:var(--dshpc-fg-3,rgba(128,128,128,.8));padding-bottom:10px;white-space:nowrap;}\";\n//# sourceMappingURL=session-css.generated.js.map","import { createStyleKit } from '../design/index.js';\nimport { BACK_TO_TOP_CSS, BUTTON_CSS, DATETIME_CSS, FIELD_CSS, HINT_CSS, LOADING_CSS, SEGMENTED_CSS, } from './controls-css.js';\nimport { MARQUEE_CSS } from './marquee-css.js';\nimport { PICKER_CSS } from './picker-css.js';\nimport { FEEDBACK_CSS } from './feedback-css.js';\nimport { CARD_CSS } from './card-css.js';\nimport { CHIP_CSS } from './chip-css.js';\nimport { CODE_VIEWER_CSS } from './code-viewer-css.js';\nimport { PANEL_DOCK_CSS } from './panel-dock-css.js';\nimport { EXPLORER_CSS } from '../explorer/explorer-css.js';\nimport { SESSION_CSS } from '../session/session-css.js';\nexport const CONTROLS_DOMAIN = 'controls';\n/**\n * 全部控件样式(数组顺序不可调换:同特异性规则后注入者胜出)。\n * 导出仅供 `test/css-contract.test.mjs` 做文本自检,不作为对外 API。\n */\nexport const CONTROLS_CSS = [\n SEGMENTED_CSS,\n BUTTON_CSS,\n FIELD_CSS,\n LOADING_CSS,\n BACK_TO_TOP_CSS,\n HINT_CSS,\n PICKER_CSS,\n DATETIME_CSS,\n FEEDBACK_CSS,\n EXPLORER_CSS,\n SESSION_CSS,\n CARD_CSS,\n CHIP_CSS,\n MARQUEE_CSS,\n PANEL_DOCK_CSS,\n CODE_VIEWER_CSS,\n].join('\\n');\n/**\n * 当前插件的样式设施。\n *\n * 为什么是模块级而不是 React Context:core 会被**内联进每个插件各自的 bundle**,\n * 模块级变量天然按插件隔离(不像共享运行时那样会互相踩)。\n * 插件启动时 `setStyleKit(createStyleKit({ id }))` 一次即可;不设就走默认 kit。\n */\nlet current = createStyleKit({ id: 'dsh-plugin-core-ui' });\nexport function setStyleKit(kit) {\n current = kit;\n}\nexport function getStyleKit() {\n return current;\n}\n/** 登记 token + 控件样式并确保挂载(幂等)。 */\nexport function ensureControls(kit = current) {\n kit.registerStyle('tokens', kit.tokensCss);\n kit.applyStyle(CONTROLS_DOMAIN, CONTROLS_CSS);\n}\n//# sourceMappingURL=css.js.map","/** 两种输入归一成 groups:给了 `options` 就当成一个无标题的组。 */\nexport function toGroups(groups, options) {\n if (groups !== undefined && groups.length > 0)\n return groups;\n const flat = options ?? [];\n return flat.length === 0 ? [] : [{ value: '', label: '', options: flat }];\n}\nexport function flattenOptions(groups) {\n const out = [];\n for (const g of groups)\n out.push(...g.options);\n return out;\n}\n/** 按关键词过滤(大小写不敏感,匹配 label;整组无命中则整组去掉)。 */\nexport function filterGroups(groups, query) {\n const q = query.trim().toLowerCase();\n if (q === '')\n return groups;\n const out = [];\n for (const g of groups) {\n const hit = g.options.filter((o) => o.label.toLowerCase().includes(q));\n if (hit.length > 0)\n out.push({ ...g, options: hit });\n }\n return out;\n}\n/** 多选切换;`max` 达到上限时不再添加(返回原数组,不静默截断)。 */\nexport function toggleValue(current, value, max) {\n const idx = current.indexOf(value);\n if (idx >= 0)\n return current.filter((v) => v !== value);\n if (max !== undefined && current.length >= max)\n return [...current];\n return [...current, value];\n}\nexport function labelsOf(groups, values) {\n const all = flattenOptions(groups);\n const out = [];\n for (const v of values) {\n const hit = all.find((o) => o.value === v);\n if (hit !== undefined)\n out.push(hit.label);\n }\n return out;\n}\n/** 值落在哪个组里(按模型值反推供应商等场景)。 */\nexport function groupOf(groups, value) {\n if (value === '')\n return undefined;\n return groups.find((g) => g.options.some((o) => o.value === value));\n}\n//# sourceMappingURL=picker-logic.js.map","function hasWindow() {\n return typeof window !== 'undefined';\n}\nfunction getNodeName(node) {\n if (isNode(node)) {\n return (node.nodeName || '').toLowerCase();\n }\n // Mocked nodes in testing environments may not be instances of Node. By\n // returning `#document` an infinite loop won't occur.\n // https://github.com/floating-ui/floating-ui/issues/2317\n return '#document';\n}\nfunction getWindow(node) {\n var _node$ownerDocument;\n return (node == null || (_node$ownerDocument = node.ownerDocument) == null ? void 0 : _node$ownerDocument.defaultView) || window;\n}\nfunction getDocumentElement(node) {\n var _ref;\n return (_ref = (isNode(node) ? node.ownerDocument : node.document) || window.document) == null ? void 0 : _ref.documentElement;\n}\nfunction isNode(value) {\n if (!hasWindow()) {\n return false;\n }\n return value instanceof Node || value instanceof getWindow(value).Node;\n}\nfunction isElement(value) {\n if (!hasWindow()) {\n return false;\n }\n return value instanceof Element || value instanceof getWindow(value).Element;\n}\nfunction isHTMLElement(value) {\n if (!hasWindow()) {\n return false;\n }\n return value instanceof HTMLElement || value instanceof getWindow(value).HTMLElement;\n}\nfunction isShadowRoot(value) {\n if (!hasWindow() || typeof ShadowRoot === 'undefined') {\n return false;\n }\n return value instanceof ShadowRoot || value instanceof getWindow(value).ShadowRoot;\n}\nfunction isOverflowElement(element) {\n const {\n overflow,\n overflowX,\n overflowY,\n display\n } = getComputedStyle(element);\n return /auto|scroll|overlay|hidden|clip/.test(overflow + overflowY + overflowX) && display !== 'inline' && display !== 'contents';\n}\nfunction isTableElement(element) {\n return /^(table|td|th)$/.test(getNodeName(element));\n}\nfunction isTopLayer(element) {\n try {\n if (element.matches(':popover-open')) {\n return true;\n }\n } catch (_e) {\n // no-op\n }\n try {\n return element.matches(':modal');\n } catch (_e) {\n return false;\n }\n}\nconst willChangeRe = /transform|translate|scale|rotate|perspective|filter/;\nconst containRe = /paint|layout|strict|content/;\nconst isNotNone = value => !!value && value !== 'none';\nlet isWebKitValue;\nfunction isContainingBlock(elementOrCss) {\n const css = isElement(elementOrCss) ? getComputedStyle(elementOrCss) : elementOrCss;\n\n // https://developer.mozilla.org/en-US/docs/Web/CSS/Containing_block#identifying_the_containing_block\n // https://drafts.csswg.org/css-transforms-2/#individual-transforms\n return isNotNone(css.transform) || isNotNone(css.translate) || isNotNone(css.scale) || isNotNone(css.rotate) || isNotNone(css.perspective) || !isWebKit() && (isNotNone(css.backdropFilter) || isNotNone(css.filter)) || willChangeRe.test(css.willChange || '') || containRe.test(css.contain || '');\n}\nfunction getContainingBlock(element) {\n let currentNode = getParentNode(element);\n while (isHTMLElement(currentNode) && !isLastTraversableNode(currentNode)) {\n if (isContainingBlock(currentNode)) {\n return currentNode;\n } else if (isTopLayer(currentNode)) {\n return null;\n }\n currentNode = getParentNode(currentNode);\n }\n return null;\n}\nfunction isWebKit() {\n if (isWebKitValue == null) {\n isWebKitValue = typeof CSS !== 'undefined' && CSS.supports && CSS.supports('-webkit-backdrop-filter', 'none');\n }\n return isWebKitValue;\n}\nfunction isLastTraversableNode(node) {\n return /^(html|body|#document)$/.test(getNodeName(node));\n}\nfunction getComputedStyle(element) {\n return getWindow(element).getComputedStyle(element);\n}\nfunction getNodeScroll(element) {\n if (isElement(element)) {\n return {\n scrollLeft: element.scrollLeft,\n scrollTop: element.scrollTop\n };\n }\n return {\n scrollLeft: element.scrollX,\n scrollTop: element.scrollY\n };\n}\nfunction getParentNode(node) {\n if (getNodeName(node) === 'html') {\n return node;\n }\n const result =\n // Step into the shadow DOM of the parent of a slotted node.\n node.assignedSlot ||\n // DOM Element detected.\n node.parentNode ||\n // ShadowRoot detected.\n isShadowRoot(node) && node.host ||\n // Fallback.\n getDocumentElement(node);\n return isShadowRoot(result) ? result.host : result;\n}\nfunction getNearestOverflowAncestor(node) {\n const parentNode = getParentNode(node);\n if (isLastTraversableNode(parentNode)) {\n return (node.ownerDocument || node).body;\n }\n if (isHTMLElement(parentNode) && isOverflowElement(parentNode)) {\n return parentNode;\n }\n return getNearestOverflowAncestor(parentNode);\n}\nfunction getOverflowAncestors(node, list, traverseIframes) {\n var _node$ownerDocument2;\n if (list === void 0) {\n list = [];\n }\n if (traverseIframes === void 0) {\n traverseIframes = true;\n }\n const scrollableAncestor = getNearestOverflowAncestor(node);\n const isBody = scrollableAncestor === ((_node$ownerDocument2 = node.ownerDocument) == null ? void 0 : _node$ownerDocument2.body);\n const win = getWindow(scrollableAncestor);\n if (isBody) {\n const frameElement = getFrameElement(win);\n return list.concat(win, win.visualViewport || [], isOverflowElement(scrollableAncestor) ? scrollableAncestor : [], frameElement && traverseIframes ? getOverflowAncestors(frameElement) : []);\n } else {\n return list.concat(scrollableAncestor, getOverflowAncestors(scrollableAncestor, [], traverseIframes));\n }\n}\nfunction getFrameElement(win) {\n return win.parent && Object.getPrototypeOf(win.parent) ? win.frameElement : null;\n}\n\nexport { getComputedStyle, getContainingBlock, getDocumentElement, getFrameElement, getNearestOverflowAncestor, getNodeName, getNodeScroll, getOverflowAncestors, getParentNode, getWindow, isContainingBlock, isElement, isHTMLElement, isLastTraversableNode, isNode, isOverflowElement, isShadowRoot, isTableElement, isTopLayer, isWebKit };\n","/**\n * Custom positioning reference element.\n * @see https://floating-ui.com/docs/virtual-elements\n */\n\nconst sides = ['top', 'right', 'bottom', 'left'];\nconst alignments = ['start', 'end'];\nconst placements = /*#__PURE__*/sides.reduce((acc, side) => acc.concat(side, side + \"-\" + alignments[0], side + \"-\" + alignments[1]), []);\nconst min = Math.min;\nconst max = Math.max;\nconst round = Math.round;\nconst floor = Math.floor;\nconst createCoords = v => ({\n x: v,\n y: v\n});\nconst oppositeSideMap = {\n left: 'right',\n right: 'left',\n bottom: 'top',\n top: 'bottom'\n};\nfunction clamp(start, value, end) {\n return max(start, min(value, end));\n}\nfunction evaluate(value, param) {\n return typeof value === 'function' ? value(param) : value;\n}\nfunction getSide(placement) {\n return placement.split('-')[0];\n}\nfunction getAlignment(placement) {\n return placement.split('-')[1];\n}\nfunction getOppositeAxis(axis) {\n return axis === 'x' ? 'y' : 'x';\n}\nfunction getAxisLength(axis) {\n return axis === 'y' ? 'height' : 'width';\n}\nfunction getSideAxis(placement) {\n const firstChar = placement[0];\n return firstChar === 't' || firstChar === 'b' ? 'y' : 'x';\n}\nfunction getAlignmentAxis(placement) {\n return getOppositeAxis(getSideAxis(placement));\n}\nfunction getAlignmentSides(placement, rects, rtl) {\n if (rtl === void 0) {\n rtl = false;\n }\n const alignment = getAlignment(placement);\n const alignmentAxis = getAlignmentAxis(placement);\n const length = getAxisLength(alignmentAxis);\n let mainAlignmentSide = alignmentAxis === 'x' ? alignment === (rtl ? 'end' : 'start') ? 'right' : 'left' : alignment === 'start' ? 'bottom' : 'top';\n if (rects.reference[length] > rects.floating[length]) {\n mainAlignmentSide = getOppositePlacement(mainAlignmentSide);\n }\n return [mainAlignmentSide, getOppositePlacement(mainAlignmentSide)];\n}\nfunction getExpandedPlacements(placement) {\n const oppositePlacement = getOppositePlacement(placement);\n return [getOppositeAlignmentPlacement(placement), oppositePlacement, getOppositeAlignmentPlacement(oppositePlacement)];\n}\nfunction getOppositeAlignmentPlacement(placement) {\n return placement.includes('start') ? placement.replace('start', 'end') : placement.replace('end', 'start');\n}\nconst lrPlacement = ['left', 'right'];\nconst rlPlacement = ['right', 'left'];\nconst tbPlacement = ['top', 'bottom'];\nconst btPlacement = ['bottom', 'top'];\nfunction getSideList(side, isStart, rtl) {\n switch (side) {\n case 'top':\n case 'bottom':\n if (rtl) return isStart ? rlPlacement : lrPlacement;\n return isStart ? lrPlacement : rlPlacement;\n case 'left':\n case 'right':\n return isStart ? tbPlacement : btPlacement;\n default:\n return [];\n }\n}\nfunction getOppositeAxisPlacements(placement, flipAlignment, direction, rtl) {\n const alignment = getAlignment(placement);\n let list = getSideList(getSide(placement), direction === 'start', rtl);\n if (alignment) {\n list = list.map(side => side + \"-\" + alignment);\n if (flipAlignment) {\n list = list.concat(list.map(getOppositeAlignmentPlacement));\n }\n }\n return list;\n}\nfunction getOppositePlacement(placement) {\n const side = getSide(placement);\n return oppositeSideMap[side] + placement.slice(side.length);\n}\nfunction expandPaddingObject(padding) {\n var _padding$top, _padding$right, _padding$bottom, _padding$left;\n return {\n top: (_padding$top = padding.top) != null ? _padding$top : 0,\n right: (_padding$right = padding.right) != null ? _padding$right : 0,\n bottom: (_padding$bottom = padding.bottom) != null ? _padding$bottom : 0,\n left: (_padding$left = padding.left) != null ? _padding$left : 0\n };\n}\nfunction getPaddingObject(padding) {\n return typeof padding !== 'number' ? expandPaddingObject(padding) : {\n top: padding,\n right: padding,\n bottom: padding,\n left: padding\n };\n}\nfunction rectToClientRect(rect) {\n const {\n x,\n y,\n width,\n height\n } = rect;\n return {\n width,\n height,\n top: y,\n left: x,\n right: x + width,\n bottom: y + height,\n x,\n y\n };\n}\n\nexport { alignments, clamp, createCoords, evaluate, expandPaddingObject, floor, getAlignment, getAlignmentAxis, getAlignmentSides, getAxisLength, getExpandedPlacements, getOppositeAlignmentPlacement, getOppositeAxis, getOppositeAxisPlacements, getOppositePlacement, getPaddingObject, getSide, getSideAxis, max, min, placements, rectToClientRect, round, sides };\n","/*!\n* tabbable 6.5.1\n* @license MIT, https://github.com/focus-trap/tabbable/blob/master/LICENSE\n*/\n'use strict';\n\n// NOTE: separate `:not()` selectors has broader browser support than the newer\n// `:not([inert], [inert] *)` (Feb 2023)\nvar candidateSelectors = ['input:not([inert]):not([inert] *)', 'select:not([inert]):not([inert] *)', 'textarea:not([inert]):not([inert] *)', 'a[href]:not([inert]):not([inert] *)', 'area[href]:not([inert]):not([inert] *)', 'button:not([inert]):not([inert] *)', '[tabindex]:not(slot):not([inert]):not([inert] *)', 'audio[controls]:not([inert]):not([inert] *)', 'video[controls]:not([inert]):not([inert] *)', '[contenteditable]:not([contenteditable=\"false\"]):not([inert]):not([inert] *)', 'details>summary:first-of-type:not([inert]):not([inert] *)', 'details:not([inert]):not([inert] *)'];\nvar candidateSelector = /* #__PURE__ */candidateSelectors.join(',');\nvar NoElement = typeof Element === 'undefined';\nvar matches = NoElement ? function () {} : Element.prototype.matches || Element.prototype.msMatchesSelector || Element.prototype.webkitMatchesSelector;\nvar getRootNode = !NoElement && Element.prototype.getRootNode ? function (element) {\n return element == null || element.getRootNode == null ? void 0 : element.getRootNode();\n} : function (element) {\n return element == null ? void 0 : element.ownerDocument;\n};\n\n/**\n * Determines if a node is inert or in an inert ancestor.\n * @param {Node} [node]\n * @param {boolean} [lookUp] If true and `node` is not inert, looks up at ancestors to\n * see if any of them are inert. If false, only `node` itself is considered.\n * @returns {boolean} True if inert itself or by way of being in an inert ancestor.\n * False if `node` is falsy.\n */\nvar _isInert = function isInert(node, lookUp) {\n if (lookUp === void 0) {\n lookUp = true;\n }\n // CAREFUL: JSDom does not support inert at all, so we can't use the `HTMLElement.inert`\n // JS API property; we have to check the attribute, which can either be empty or 'true';\n // if it's `null` (not specified) or 'false', it's an active element\n var inertAtt = node == null || node.getAttribute == null ? void 0 : node.getAttribute('inert');\n var inert = inertAtt === '' || inertAtt === 'true';\n\n // NOTE: this could also be handled with `node.matches('[inert], :is([inert] *)')`\n // if it weren't for `matches()` not being a function on shadow roots; the following\n // code works for any kind of node\n var result = inert || lookUp && node && (\n // closest does not exist on shadow roots, so we fall back to a manual\n // lookup upward, in case it is not defined.\n typeof node.closest === 'function' ? node.closest('[inert]') : _isInert(node.parentNode));\n return result;\n};\n\n/**\n * Determines if a node's content is editable.\n * @param {Element} [node]\n * @returns True if it's content-editable; false if it's not or `node` is falsy.\n */\nvar isContentEditable = function isContentEditable(node) {\n var _node$getAttribute;\n // CAREFUL: JSDom does not support the `HTMLElement.isContentEditable` API so we have\n // to use the case-insensitive attribute directly: empty, 'true', and 'plaintext-only'\n // are editable states; `null` (not specified) and 'false' are not.\n var attValue = node == null || node.getAttribute == null || (_node$getAttribute = node.getAttribute('contenteditable')) == null ? void 0 : _node$getAttribute.toLowerCase();\n return attValue === '' || attValue === 'true' || attValue === 'plaintext-only';\n};\n\n/**\n * @param {Element} el container to check in\n * @param {boolean} includeContainer add container to check\n * @param {(node: Element) => boolean} filter filter candidates\n * @returns {Element[]}\n */\nvar getCandidates = function getCandidates(el, includeContainer, filter) {\n // even if `includeContainer=false`, we still have to check it for inertness because\n // if it's inert (either by itself or via its parent), then all its children are inert\n if (_isInert(el)) {\n return [];\n }\n var candidates = Array.prototype.slice.apply(el.querySelectorAll(candidateSelector));\n if (includeContainer && matches.call(el, candidateSelector)) {\n candidates.unshift(el);\n }\n candidates = candidates.filter(filter);\n return candidates;\n};\n\n/**\n * @callback GetShadowRoot\n * @param {Element} element to check for shadow root\n * @returns {ShadowRoot|boolean} ShadowRoot if available or boolean indicating if a shadowRoot is attached but not available.\n */\n\n/**\n * @callback ShadowRootFilter\n * @param {Element} shadowHostNode the element which contains shadow content\n * @returns {boolean} true if a shadow root could potentially contain valid candidates.\n */\n\n/**\n * @typedef {Object} CandidateScope\n * @property {Element} scopeParent contains inner candidates\n * @property {Element[]} candidates list of candidates found in the scope parent\n */\n\n/**\n * @typedef {Object} IterativeOptions\n * @property {GetShadowRoot|boolean} getShadowRoot true if shadow support is enabled; falsy if not;\n * if a function, implies shadow support is enabled and either returns the shadow root of an element\n * or a boolean stating if it has an undisclosed shadow root\n * @property {(node: Element) => boolean} filter filter candidates\n * @property {boolean} flatten if true then result will flatten any CandidateScope into the returned list\n * @property {ShadowRootFilter} shadowRootFilter filter shadow roots;\n */\n\n/**\n * @param {Element[]} elements list of element containers to match candidates from\n * @param {boolean} includeContainer add container list to check\n * @param {IterativeOptions} options\n * @returns {Array.<Element|CandidateScope>}\n */\nvar _getCandidatesIteratively = function getCandidatesIteratively(elements, includeContainer, options) {\n var candidates = [];\n var elementsToCheck = Array.from(elements);\n while (elementsToCheck.length) {\n var element = elementsToCheck.shift();\n if (_isInert(element, false)) {\n // no need to look up since we're drilling down\n // anything inside this container will also be inert\n continue;\n }\n if (element.tagName === 'SLOT') {\n // add shadow dom slot scope (slot itself cannot be focusable)\n var assigned = element.assignedElements();\n var content = assigned.length ? assigned : element.children;\n var nestedCandidates = _getCandidatesIteratively(content, true, options);\n if (options.flatten) {\n candidates.push.apply(candidates, nestedCandidates);\n } else {\n candidates.push({\n scopeParent: element,\n candidates: nestedCandidates\n });\n }\n } else {\n // check candidate element\n var validCandidate = matches.call(element, candidateSelector);\n if (validCandidate && options.filter(element) && (includeContainer || !elements.includes(element))) {\n candidates.push(element);\n }\n\n // iterate over shadow content if possible\n var shadowRoot = element.shadowRoot ||\n // check for an undisclosed shadow\n typeof options.getShadowRoot === 'function' && options.getShadowRoot(element);\n\n // no inert look up because we're already drilling down and checking for inertness\n // on the way down, so all containers to this root node should have already been\n // vetted as non-inert\n var validShadowRoot = !_isInert(shadowRoot, false) && (!options.shadowRootFilter || options.shadowRootFilter(element));\n if (shadowRoot && validShadowRoot) {\n // add shadow dom scope IIF a shadow root node was given; otherwise, an undisclosed\n // shadow exists, so look at light dom children as fallback BUT create a scope for any\n // child candidates found because they're likely slotted elements (elements that are\n // children of the web component element (which has the shadow), in the light dom, but\n // slotted somewhere _inside_ the undisclosed shadow) -- the scope is created below,\n // _after_ we return from this recursive call\n var _nestedCandidates = _getCandidatesIteratively(shadowRoot === true ? element.children : shadowRoot.children, true, options);\n if (options.flatten) {\n candidates.push.apply(candidates, _nestedCandidates);\n } else {\n candidates.push({\n scopeParent: element,\n candidates: _nestedCandidates\n });\n }\n } else {\n // there's not shadow so just dig into the element's (light dom) children\n // __without__ giving the element special scope treatment\n elementsToCheck.unshift.apply(elementsToCheck, element.children);\n }\n }\n }\n return candidates;\n};\n\n/**\n * @private\n * Determines if the node has an explicitly specified `tabindex` attribute.\n * @param {HTMLElement} node\n * @returns {boolean} True if so; false if not.\n */\nvar hasTabIndex = function hasTabIndex(node) {\n return !isNaN(parseInt(node.getAttribute('tabindex'), 10));\n};\n\n/**\n * Determine the tab index of a given node.\n * @param {HTMLElement} node\n * @returns {number} Tab order (negative, 0, or positive number).\n * @throws {Error} If `node` is falsy.\n */\nvar getTabIndex = function getTabIndex(node) {\n if (!node) {\n throw new Error('No node provided');\n }\n if (node.tabIndex < 0) {\n // in Chrome, <details/>, <audio controls/> and <video controls/> elements get a default\n // `tabIndex` of -1 when the 'tabindex' attribute isn't specified in the DOM,\n // yet they are still part of the regular tab order; in FF, they get a default\n // `tabIndex` of 0; since Chrome still puts those elements in the regular tab\n // order, consider their tab index to be 0.\n // Also browsers do not return `tabIndex` correctly for contentEditable nodes;\n // so if they don't have a tabindex attribute specifically set, assume it's 0.\n if ((/^(AUDIO|VIDEO|DETAILS)$/.test(node.tagName) || isContentEditable(node)) && !hasTabIndex(node)) {\n return 0;\n }\n }\n return node.tabIndex;\n};\n\n/**\n * Determine the tab index of a given node __for sort order purposes__.\n * @param {HTMLElement} node\n * @param {boolean} [isScope] True for a custom element with shadow root or slot that, by default,\n * has tabIndex -1, but needs to be sorted by document order in order for its content to be\n * inserted into the correct sort position.\n * @returns {number} Tab order (negative, 0, or positive number).\n */\nvar getSortOrderTabIndex = function getSortOrderTabIndex(node, isScope) {\n var tabIndex = getTabIndex(node);\n if (tabIndex < 0 && isScope && !hasTabIndex(node)) {\n return 0;\n }\n return tabIndex;\n};\nvar sortOrderedTabbables = function sortOrderedTabbables(a, b) {\n return a.tabIndex === b.tabIndex ? a.documentOrder - b.documentOrder : a.tabIndex - b.tabIndex;\n};\nvar isInput = function isInput(node) {\n return node.tagName === 'INPUT';\n};\nvar isHiddenInput = function isHiddenInput(node) {\n return isInput(node) && node.type === 'hidden';\n};\nvar isDetailsWithSummary = function isDetailsWithSummary(node) {\n var r = node.tagName === 'DETAILS' && Array.prototype.slice.apply(node.children).some(function (child) {\n return child.tagName === 'SUMMARY';\n });\n return r;\n};\nvar getCheckedRadio = function getCheckedRadio(nodes, form) {\n for (var i = 0; i < nodes.length; i++) {\n if (nodes[i].checked && nodes[i].form === form) {\n return nodes[i];\n }\n }\n};\nvar isTabbableRadio = function isTabbableRadio(node) {\n if (!node.name) {\n return true;\n }\n var radioScope = node.form || getRootNode(node);\n var queryRadios = function queryRadios(name) {\n return radioScope.querySelectorAll('input[type=\"radio\"][name=\"' + name + '\"]');\n };\n var radioSet;\n if (typeof window !== 'undefined' && typeof window.CSS !== 'undefined' && typeof window.CSS.escape === 'function') {\n radioSet = queryRadios(window.CSS.escape(node.name));\n } else {\n try {\n radioSet = queryRadios(node.name);\n } catch (err) {\n // eslint-disable-next-line no-console\n console.error('Looks like you have a radio button with a name attribute containing invalid CSS selector characters and need the CSS.escape polyfill: %s', err.message);\n return false;\n }\n }\n var checked = getCheckedRadio(radioSet, node.form);\n return !checked || checked === node;\n};\nvar isRadio = function isRadio(node) {\n return isInput(node) && node.type === 'radio';\n};\nvar isNonTabbableRadio = function isNonTabbableRadio(node) {\n return isRadio(node) && !isTabbableRadio(node);\n};\n\n// determines if a node is ultimately attached to the window's document\nvar isNodeAttached = function isNodeAttached(node) {\n var _nodeRoot;\n // The root node is the shadow root if the node is in a shadow DOM; some document otherwise\n // (but NOT _the_ document; see second 'If' comment below for more).\n // If rootNode is shadow root, it'll have a host, which is the element to which the shadow\n // is attached, and the one we need to check if it's in the document or not (because the\n // shadow, and all nodes it contains, is never considered in the document since shadows\n // behave like self-contained DOMs; but if the shadow's HOST, which is part of the document,\n // is hidden, or is not in the document itself but is detached, it will affect the shadow's\n // visibility, including all the nodes it contains). The host could be any normal node,\n // or a custom element (i.e. web component). Either way, that's the one that is considered\n // part of the document, not the shadow root, nor any of its children (i.e. the node being\n // tested).\n // To further complicate things, we have to look all the way up until we find a shadow HOST\n // that is attached (or find none) because the node might be in nested shadows...\n // If rootNode is not a shadow root, it won't have a host, and so rootNode should be the\n // document (per the docs) and while it's a Document-type object, that document does not\n // appear to be the same as the node's `ownerDocument` for some reason, so it's safer\n // to ignore the rootNode at this point, and use `node.ownerDocument`. Otherwise,\n // using `rootNode.contains(node)` will _always_ be true we'll get false-positives when\n // node is actually detached.\n // NOTE: If `nodeRootHost` or `node` happens to be the `document` itself (which is possible\n // if a tabbable/focusable node was quickly added to the DOM, focused, and then removed\n // from the DOM as in https://github.com/focus-trap/focus-trap-react/issues/905), then\n // `ownerDocument` will be `null`, hence the optional chaining on it.\n var nodeRoot = node && getRootNode(node);\n var nodeRootHost = (_nodeRoot = nodeRoot) == null ? void 0 : _nodeRoot.host;\n\n // in some cases, a detached node will return itself as the root instead of a document or\n // shadow root object, in which case, we shouldn't try to look further up the host chain\n var attached = false;\n if (nodeRoot && nodeRoot !== node) {\n var _nodeRootHost, _node$ownerDocument;\n attached = !!((_nodeRootHost = nodeRootHost) != null && (_nodeRootHost = _nodeRootHost.ownerDocument) != null && _nodeRootHost.contains(nodeRootHost) || node != null && (_node$ownerDocument = node.ownerDocument) != null && _node$ownerDocument.contains(node));\n while (!attached && nodeRootHost) {\n var _nodeRoot2, _nodeRootHost2;\n // since it's not attached and we have a root host, the node MUST be in a nested shadow DOM,\n // which means we need to get the host's host and check if that parent host is contained\n // in (i.e. attached to) the document\n nodeRoot = getRootNode(nodeRootHost);\n nodeRootHost = (_nodeRoot2 = nodeRoot) == null ? void 0 : _nodeRoot2.host;\n attached = !!((_nodeRootHost2 = nodeRootHost) != null && (_nodeRootHost2 = _nodeRootHost2.ownerDocument) != null && _nodeRootHost2.contains(nodeRootHost));\n }\n }\n return attached;\n};\nvar isZeroArea = function isZeroArea(node) {\n var _node$getBoundingClie = node.getBoundingClientRect(),\n width = _node$getBoundingClie.width,\n height = _node$getBoundingClie.height;\n return width === 0 && height === 0;\n};\nvar isHidden = function isHidden(node, _ref) {\n var displayCheck = _ref.displayCheck,\n getShadowRoot = _ref.getShadowRoot;\n if (displayCheck === 'full-native') {\n if ('checkVisibility' in node) {\n // Chrome >= 105, Edge >= 105, Firefox >= 106, Safari >= 17.4\n // @see https://developer.mozilla.org/en-US/docs/Web/API/Element/checkVisibility#browser_compatibility\n var visible = node.checkVisibility({\n // Checking opacity might be desirable for some use cases, but natively,\n // opacity zero elements _are_ focusable and tabbable.\n checkOpacity: false,\n opacityProperty: false,\n contentVisibilityAuto: true,\n visibilityProperty: true,\n // This is an alias for `visibilityProperty`. Contemporary browsers\n // support both. However, this alias has wider browser support (Chrome\n // >= 105 and Firefox >= 106, vs. Chrome >= 121 and Firefox >= 122), so\n // we include it anyway.\n checkVisibilityCSS: true\n });\n return !visible;\n }\n // Fall through to manual visibility checks\n }\n\n // NOTE: visibility will be `undefined` if node is detached from the document\n // (see notes about this further down), which means we will consider it visible\n // (this is legacy behavior from a very long way back)\n // NOTE: we check this regardless of `displayCheck=\"none\"` because this is a\n // _visibility_ check, not a _display_ check\n var _getComputedStyle = getComputedStyle(node),\n visibility = _getComputedStyle.visibility;\n if (visibility === 'hidden' || visibility === 'collapse') {\n return true;\n }\n var isDirectSummary = matches.call(node, 'details>summary:first-of-type');\n var nodeUnderDetails = isDirectSummary ? node.parentElement : node;\n if (matches.call(nodeUnderDetails, 'details:not([open]) *')) {\n return true;\n }\n if (!displayCheck || displayCheck === 'full' ||\n // full-native can run this branch when it falls through in case\n // Element#checkVisibility is unsupported\n displayCheck === 'full-native' || displayCheck === 'legacy-full') {\n if (typeof getShadowRoot === 'function') {\n // figure out if we should consider the node to be in an undisclosed shadow and use the\n // 'non-zero-area' fallback\n var originalNode = node;\n while (node) {\n var parentElement = node.parentElement;\n var rootNode = getRootNode(node);\n if (parentElement && !parentElement.shadowRoot && getShadowRoot(parentElement) === true // check if there's an undisclosed shadow\n ) {\n // node has an undisclosed shadow which means we can only treat it as a black box, so we\n // fall back to a non-zero-area test\n return isZeroArea(node);\n } else if (node.assignedSlot) {\n // iterate up slot\n node = node.assignedSlot;\n } else if (!parentElement && rootNode !== node.ownerDocument) {\n // cross shadow boundary\n node = rootNode.host;\n } else {\n // iterate up normal dom\n node = parentElement;\n }\n }\n node = originalNode;\n }\n // else, `getShadowRoot` might be true, but all that does is enable shadow DOM support\n // (i.e. it does not also presume that all nodes might have undisclosed shadows); or\n // it might be a falsy value, which means shadow DOM support is disabled\n\n // Since we didn't find it sitting in an undisclosed shadow (or shadows are disabled)\n // now we can just test to see if it would normally be visible or not, provided it's\n // attached to the main document.\n // NOTE: We must consider case where node is inside a shadow DOM and given directly to\n // `isTabbable()` or `isFocusable()` -- regardless of `getShadowRoot` option setting.\n\n if (isNodeAttached(node)) {\n // this works wherever the node is: if there's at least one client rect, it's\n // somehow displayed; it also covers the CSS 'display: contents' case where the\n // node itself is hidden in place of its contents; and there's no need to search\n // up the hierarchy either\n return !node.getClientRects().length;\n }\n\n // Else, the node isn't attached to the document, which means the `getClientRects()`\n // API will __always__ return zero rects (this can happen, for example, if React\n // is used to render nodes onto a detached tree, as confirmed in this thread:\n // https://github.com/facebook/react/issues/9117#issuecomment-284228870)\n //\n // It also means that even window.getComputedStyle(node).display will return `undefined`\n // because styles are only computed for nodes that are in the document.\n //\n // NOTE: THIS HAS BEEN THE CASE FOR YEARS. It is not new, nor is it caused by tabbable\n // somehow. Though it was never stated officially, anyone who has ever used tabbable\n // APIs on nodes in detached containers has actually implicitly used tabbable in what\n // was later (as of v5.2.0 on Apr 9, 2021) called `displayCheck=\"none\"` mode -- essentially\n // considering __everything__ to be visible because of the innability to determine styles.\n //\n // v6.0.0: As of this major release, the default 'full' option __no longer treats detached\n // nodes as visible with the 'none' fallback.__\n if (displayCheck !== 'legacy-full') {\n return true; // hidden\n }\n // else, fallback to 'none' mode and consider the node visible\n } else if (displayCheck === 'non-zero-area') {\n // NOTE: Even though this tests that the node's client rect is non-zero to determine\n // whether it's displayed, and that a detached node will __always__ have a zero-area\n // client rect, we don't special-case for whether the node is attached or not. In\n // this mode, we do want to consider nodes that have a zero area to be hidden at all\n // times, and that includes attached or not.\n return isZeroArea(node);\n }\n\n // visible, as far as we can tell, or per current `displayCheck=none` mode, we assume\n // it's visible\n return false;\n};\n\n// form fields (nested) inside a disabled fieldset are not focusable/tabbable\n// unless they are in the _first_ <legend> element of the top-most disabled\n// fieldset\nvar isDisabledFromFieldset = function isDisabledFromFieldset(node) {\n if (/^(INPUT|BUTTON|SELECT|TEXTAREA)$/.test(node.tagName)) {\n var parentNode = node.parentElement;\n // check if `node` is contained in a disabled <fieldset>\n while (parentNode) {\n if (parentNode.tagName === 'FIELDSET' && parentNode.disabled) {\n // look for the first <legend> among the children of the disabled <fieldset>\n for (var i = 0; i < parentNode.children.length; i++) {\n var child = parentNode.children.item(i);\n // when the first <legend> (in document order) is found\n if (child.tagName === 'LEGEND') {\n // if its parent <fieldset> is not nested in another disabled <fieldset>,\n // return whether `node` is a descendant of its first <legend>\n return matches.call(parentNode, 'fieldset[disabled] *') ? true : !child.contains(node);\n }\n }\n // the disabled <fieldset> containing `node` has no <legend>\n return true;\n }\n parentNode = parentNode.parentElement;\n }\n }\n\n // else, node's tabbable/focusable state should not be affected by a fieldset's\n // enabled/disabled state\n return false;\n};\nvar isNodeMatchingSelectorFocusable = function isNodeMatchingSelectorFocusable(options, node) {\n if (node.disabled || isHiddenInput(node) || isHidden(node, options) ||\n // For a details element with a summary, the summary element gets the focus\n isDetailsWithSummary(node) || isDisabledFromFieldset(node)) {\n return false;\n }\n return true;\n};\nvar isNodeMatchingSelectorTabbable = function isNodeMatchingSelectorTabbable(options, node) {\n if (isNonTabbableRadio(node) || getTabIndex(node) < 0 || !isNodeMatchingSelectorFocusable(options, node)) {\n return false;\n }\n return true;\n};\nvar isShadowRootTabbable = function isShadowRootTabbable(shadowHostNode) {\n var tabIndex = parseInt(shadowHostNode.getAttribute('tabindex'), 10);\n if (isNaN(tabIndex) || tabIndex >= 0) {\n return true;\n }\n // If a custom element has an explicit negative tabindex,\n // browsers will not allow tab targeting said element's children.\n return false;\n};\n\n/**\n * @param {Array.<Element|CandidateScope>} candidates\n * @returns Element[]\n */\nvar _sortByOrder = function sortByOrder(candidates) {\n var regularTabbables = [];\n var orderedTabbables = [];\n candidates.forEach(function (item, i) {\n var isScope = !!item.scopeParent;\n var element = isScope ? item.scopeParent : item;\n var candidateTabindex = getSortOrderTabIndex(element, isScope);\n var elements = isScope ? _sortByOrder(item.candidates) : element;\n if (candidateTabindex === 0) {\n isScope ? regularTabbables.push.apply(regularTabbables, elements) : regularTabbables.push(element);\n } else {\n orderedTabbables.push({\n documentOrder: i,\n tabIndex: candidateTabindex,\n item: item,\n isScope: isScope,\n content: elements\n });\n }\n });\n return orderedTabbables.sort(sortOrderedTabbables).reduce(function (acc, sortable) {\n sortable.isScope ? acc.push.apply(acc, sortable.content) : acc.push(sortable.content);\n return acc;\n }, []).concat(regularTabbables);\n};\nvar tabbable = function tabbable(container, options) {\n options = options || {};\n var candidates;\n if (options.getShadowRoot) {\n candidates = _getCandidatesIteratively([container], options.includeContainer, {\n filter: isNodeMatchingSelectorTabbable.bind(null, options),\n flatten: false,\n getShadowRoot: options.getShadowRoot,\n shadowRootFilter: isShadowRootTabbable\n });\n } else {\n candidates = getCandidates(container, options.includeContainer, isNodeMatchingSelectorTabbable.bind(null, options));\n }\n return _sortByOrder(candidates);\n};\nvar focusable = function focusable(container, options) {\n options = options || {};\n var candidates;\n if (options.getShadowRoot) {\n candidates = _getCandidatesIteratively([container], options.includeContainer, {\n filter: isNodeMatchingSelectorFocusable.bind(null, options),\n flatten: true,\n getShadowRoot: options.getShadowRoot\n });\n } else {\n candidates = getCandidates(container, options.includeContainer, isNodeMatchingSelectorFocusable.bind(null, options));\n }\n return candidates;\n};\nvar isTabbable = function isTabbable(node, options) {\n options = options || {};\n if (!node) {\n throw new Error('No node provided');\n }\n if (matches.call(node, candidateSelector) === false) {\n return false;\n }\n return isNodeMatchingSelectorTabbable(options, node);\n};\nvar focusableCandidateSelector = /* #__PURE__ */candidateSelectors.concat('iframe:not([inert]):not([inert] *)').join(',');\nvar isFocusable = function isFocusable(node, options) {\n options = options || {};\n if (!node) {\n throw new Error('No node provided');\n }\n if (matches.call(node, focusableCandidateSelector) === false) {\n return false;\n }\n return isNodeMatchingSelectorFocusable(options, node);\n};\n\nexports.focusable = focusable;\nexports.getTabIndex = getTabIndex;\nexports.isFocusable = isFocusable;\nexports.isTabbable = isTabbable;\nexports.tabbable = tabbable;\n//# sourceMappingURL=index.js.map\n","import { isShadowRoot, isHTMLElement } from '@floating-ui/utils/dom';\nimport * as React from 'react';\nimport { useLayoutEffect } from 'react';\nimport { floor } from '@floating-ui/utils';\nimport { tabbable } from 'tabbable';\n\n// Avoid Chrome DevTools blue warning.\nfunction getPlatform() {\n const uaData = navigator.userAgentData;\n if (uaData != null && uaData.platform) {\n return uaData.platform;\n }\n return navigator.platform;\n}\nfunction getUserAgent() {\n const uaData = navigator.userAgentData;\n if (uaData && Array.isArray(uaData.brands)) {\n return uaData.brands.map(_ref => {\n let {\n brand,\n version\n } = _ref;\n return brand + \"/\" + version;\n }).join(' ');\n }\n return navigator.userAgent;\n}\nfunction isSafari() {\n // Chrome DevTools does not complain about navigator.vendor\n return /apple/i.test(navigator.vendor);\n}\nfunction isAndroid() {\n const re = /android/i;\n return re.test(getPlatform()) || re.test(getUserAgent());\n}\nfunction isMac() {\n return getPlatform().toLowerCase().startsWith('mac') && !navigator.maxTouchPoints;\n}\nfunction isJSDOM() {\n return getUserAgent().includes('jsdom/');\n}\n\nconst FOCUSABLE_ATTRIBUTE = 'data-floating-ui-focusable';\nconst TYPEABLE_SELECTOR = \"input:not([type='hidden']):not([disabled]),\" + \"[contenteditable]:not([contenteditable='false']),textarea:not([disabled])\";\nconst ARROW_LEFT = 'ArrowLeft';\nconst ARROW_RIGHT = 'ArrowRight';\nconst ARROW_UP = 'ArrowUp';\nconst ARROW_DOWN = 'ArrowDown';\n\nfunction activeElement(doc) {\n let activeElement = doc.activeElement;\n while (((_activeElement = activeElement) == null || (_activeElement = _activeElement.shadowRoot) == null ? void 0 : _activeElement.activeElement) != null) {\n var _activeElement;\n activeElement = activeElement.shadowRoot.activeElement;\n }\n return activeElement;\n}\nfunction contains(parent, child) {\n if (!parent || !child) {\n return false;\n }\n const rootNode = child.getRootNode == null ? void 0 : child.getRootNode();\n\n // First, attempt with faster native method\n if (parent.contains(child)) {\n return true;\n }\n\n // then fallback to custom implementation with Shadow DOM support\n if (rootNode && isShadowRoot(rootNode)) {\n let next = child;\n while (next) {\n if (parent === next) {\n return true;\n }\n // @ts-ignore\n next = next.parentNode || next.host;\n }\n }\n\n // Give up, the result is false\n return false;\n}\nfunction getTarget(event) {\n if ('composedPath' in event) {\n return event.composedPath()[0];\n }\n\n // TS thinks `event` is of type never as it assumes all browsers support\n // `composedPath()`, but browsers without shadow DOM don't.\n return event.target;\n}\nfunction isEventTargetWithin(event, node) {\n if (node == null) {\n return false;\n }\n if ('composedPath' in event) {\n return event.composedPath().includes(node);\n }\n\n // TS thinks `event` is of type never as it assumes all browsers support composedPath, but browsers without shadow dom don't\n const e = event;\n return e.target != null && node.contains(e.target);\n}\nfunction isRootElement(element) {\n return element.matches('html,body');\n}\nfunction getDocument(node) {\n return (node == null ? void 0 : node.ownerDocument) || document;\n}\nfunction isTypeableElement(element) {\n return isHTMLElement(element) && element.matches(TYPEABLE_SELECTOR);\n}\nfunction isTypeableCombobox(element) {\n if (!element) return false;\n return element.getAttribute('role') === 'combobox' && isTypeableElement(element);\n}\nfunction matchesFocusVisible(element) {\n // We don't want to block focus from working with `visibleOnly`\n // (JSDOM doesn't match `:focus-visible` when the element has `:focus`)\n if (!element || isJSDOM()) return true;\n try {\n return element.matches(':focus-visible');\n } catch (_e) {\n return true;\n }\n}\nfunction getFloatingFocusElement(floatingElement) {\n if (!floatingElement) {\n return null;\n }\n // Try to find the element that has `{...getFloatingProps()}` spread on it.\n // This indicates the floating element is acting as a positioning wrapper, and\n // so focus should be managed on the child element with the event handlers and\n // aria props.\n return floatingElement.hasAttribute(FOCUSABLE_ATTRIBUTE) ? floatingElement : floatingElement.querySelector(\"[\" + FOCUSABLE_ATTRIBUTE + \"]\") || floatingElement;\n}\n\nfunction getNodeChildren(nodes, id, onlyOpenChildren) {\n if (onlyOpenChildren === void 0) {\n onlyOpenChildren = true;\n }\n const directChildren = nodes.filter(node => {\n var _node$context;\n return node.parentId === id && (!onlyOpenChildren || ((_node$context = node.context) == null ? void 0 : _node$context.open));\n });\n return directChildren.flatMap(child => [child, ...getNodeChildren(nodes, child.id, onlyOpenChildren)]);\n}\nfunction getDeepestNode(nodes, id) {\n let deepestNodeId;\n let maxDepth = -1;\n function findDeepest(nodeId, depth) {\n if (depth > maxDepth) {\n deepestNodeId = nodeId;\n maxDepth = depth;\n }\n const children = getNodeChildren(nodes, nodeId);\n children.forEach(child => {\n findDeepest(child.id, depth + 1);\n });\n }\n findDeepest(id, 0);\n return nodes.find(node => node.id === deepestNodeId);\n}\nfunction getNodeAncestors(nodes, id) {\n var _nodes$find;\n let allAncestors = [];\n let currentParentId = (_nodes$find = nodes.find(node => node.id === id)) == null ? void 0 : _nodes$find.parentId;\n while (currentParentId) {\n const currentNode = nodes.find(node => node.id === currentParentId);\n currentParentId = currentNode == null ? void 0 : currentNode.parentId;\n if (currentNode) {\n allAncestors = allAncestors.concat(currentNode);\n }\n }\n return allAncestors;\n}\n\nfunction stopEvent(event) {\n event.preventDefault();\n event.stopPropagation();\n}\nfunction isReactEvent(event) {\n return 'nativeEvent' in event;\n}\n\n// License: https://github.com/adobe/react-spectrum/blob/b35d5c02fe900badccd0cf1a8f23bb593419f238/packages/@react-aria/utils/src/isVirtualEvent.ts\nfunction isVirtualClick(event) {\n // FIXME: Firefox is now emitting a deprecation warning for `mozInputSource`.\n // Try to find a workaround for this. `react-aria` source still has the check.\n if (event.mozInputSource === 0 && event.isTrusted) {\n return true;\n }\n if (isAndroid() && event.pointerType) {\n return event.type === 'click' && event.buttons === 1;\n }\n return event.detail === 0 && !event.pointerType;\n}\nfunction isVirtualPointerEvent(event) {\n if (isJSDOM()) return false;\n return !isAndroid() && event.width === 0 && event.height === 0 || isAndroid() && event.width === 1 && event.height === 1 && event.pressure === 0 && event.detail === 0 && event.pointerType === 'mouse' ||\n // iOS VoiceOver returns 0.333• for width/height.\n event.width < 1 && event.height < 1 && event.pressure === 0 && event.detail === 0 && event.pointerType === 'touch';\n}\nfunction isMouseLikePointerType(pointerType, strict) {\n // On some Linux machines with Chromium, mouse inputs return a `pointerType`\n // of \"pen\": https://github.com/floating-ui/floating-ui/issues/2015\n const values = ['mouse', 'pen'];\n if (!strict) {\n values.push('', undefined);\n }\n return values.includes(pointerType);\n}\n\nvar isClient = typeof document !== 'undefined';\n\nvar noop = function noop() {};\nvar index = isClient ? useLayoutEffect : noop;\n\n// https://github.com/mui/material-ui/issues/41190#issuecomment-2040873379\nconst SafeReact = {\n ...React\n};\n\nfunction useLatestRef(value) {\n const ref = React.useRef(value);\n index(() => {\n ref.current = value;\n });\n return ref;\n}\nconst useInsertionEffect = SafeReact.useInsertionEffect;\nconst useSafeInsertionEffect = useInsertionEffect || (fn => fn());\nfunction useEffectEvent(callback) {\n const ref = React.useRef(() => {\n if (process.env.NODE_ENV !== \"production\") {\n throw new Error('Cannot call an event handler while rendering.');\n }\n });\n useSafeInsertionEffect(() => {\n ref.current = callback;\n });\n return React.useCallback(function () {\n for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {\n args[_key] = arguments[_key];\n }\n return ref.current == null ? void 0 : ref.current(...args);\n }, []);\n}\n\nfunction isDifferentGridRow(index, cols, prevRow) {\n return Math.floor(index / cols) !== prevRow;\n}\nfunction isIndexOutOfListBounds(listRef, index) {\n return index < 0 || index >= listRef.current.length;\n}\nfunction getMinListIndex(listRef, disabledIndices) {\n return findNonDisabledListIndex(listRef, {\n disabledIndices\n });\n}\nfunction getMaxListIndex(listRef, disabledIndices) {\n return findNonDisabledListIndex(listRef, {\n decrement: true,\n startingIndex: listRef.current.length,\n disabledIndices\n });\n}\nfunction findNonDisabledListIndex(listRef, _temp) {\n let {\n startingIndex = -1,\n decrement = false,\n disabledIndices,\n amount = 1\n } = _temp === void 0 ? {} : _temp;\n let index = startingIndex;\n do {\n index += decrement ? -amount : amount;\n } while (index >= 0 && index <= listRef.current.length - 1 && isListIndexDisabled(listRef, index, disabledIndices));\n return index;\n}\nfunction getGridNavigatedIndex(listRef, _ref) {\n let {\n event,\n orientation,\n loop,\n rtl,\n cols,\n disabledIndices,\n minIndex,\n maxIndex,\n prevIndex,\n stopEvent: stop = false\n } = _ref;\n let nextIndex = prevIndex;\n if (event.key === ARROW_UP) {\n stop && stopEvent(event);\n if (prevIndex === -1) {\n nextIndex = maxIndex;\n } else {\n nextIndex = findNonDisabledListIndex(listRef, {\n startingIndex: nextIndex,\n amount: cols,\n decrement: true,\n disabledIndices\n });\n if (loop && (prevIndex - cols < minIndex || nextIndex < 0)) {\n const col = prevIndex % cols;\n const maxCol = maxIndex % cols;\n const offset = maxIndex - (maxCol - col);\n if (maxCol === col) {\n nextIndex = maxIndex;\n } else {\n nextIndex = maxCol > col ? offset : offset - cols;\n }\n }\n }\n if (isIndexOutOfListBounds(listRef, nextIndex)) {\n nextIndex = prevIndex;\n }\n }\n if (event.key === ARROW_DOWN) {\n stop && stopEvent(event);\n if (prevIndex === -1) {\n nextIndex = minIndex;\n } else {\n nextIndex = findNonDisabledListIndex(listRef, {\n startingIndex: prevIndex,\n amount: cols,\n disabledIndices\n });\n if (loop && prevIndex + cols > maxIndex) {\n nextIndex = findNonDisabledListIndex(listRef, {\n startingIndex: prevIndex % cols - cols,\n amount: cols,\n disabledIndices\n });\n }\n }\n if (isIndexOutOfListBounds(listRef, nextIndex)) {\n nextIndex = prevIndex;\n }\n }\n\n // Remains on the same row/column.\n if (orientation === 'both') {\n const prevRow = floor(prevIndex / cols);\n if (event.key === (rtl ? ARROW_LEFT : ARROW_RIGHT)) {\n stop && stopEvent(event);\n if (prevIndex % cols !== cols - 1) {\n nextIndex = findNonDisabledListIndex(listRef, {\n startingIndex: prevIndex,\n disabledIndices\n });\n if (loop && isDifferentGridRow(nextIndex, cols, prevRow)) {\n nextIndex = findNonDisabledListIndex(listRef, {\n startingIndex: prevIndex - prevIndex % cols - 1,\n disabledIndices\n });\n }\n } else if (loop) {\n nextIndex = findNonDisabledListIndex(listRef, {\n startingIndex: prevIndex - prevIndex % cols - 1,\n disabledIndices\n });\n }\n if (isDifferentGridRow(nextIndex, cols, prevRow)) {\n nextIndex = prevIndex;\n }\n }\n if (event.key === (rtl ? ARROW_RIGHT : ARROW_LEFT)) {\n stop && stopEvent(event);\n if (prevIndex % cols !== 0) {\n nextIndex = findNonDisabledListIndex(listRef, {\n startingIndex: prevIndex,\n decrement: true,\n disabledIndices\n });\n if (loop && isDifferentGridRow(nextIndex, cols, prevRow)) {\n nextIndex = findNonDisabledListIndex(listRef, {\n startingIndex: prevIndex + (cols - prevIndex % cols),\n decrement: true,\n disabledIndices\n });\n }\n } else if (loop) {\n nextIndex = findNonDisabledListIndex(listRef, {\n startingIndex: prevIndex + (cols - prevIndex % cols),\n decrement: true,\n disabledIndices\n });\n }\n if (isDifferentGridRow(nextIndex, cols, prevRow)) {\n nextIndex = prevIndex;\n }\n }\n const lastRow = floor(maxIndex / cols) === prevRow;\n if (isIndexOutOfListBounds(listRef, nextIndex)) {\n if (loop && lastRow) {\n nextIndex = event.key === (rtl ? ARROW_RIGHT : ARROW_LEFT) ? maxIndex : findNonDisabledListIndex(listRef, {\n startingIndex: prevIndex - prevIndex % cols - 1,\n disabledIndices\n });\n } else {\n nextIndex = prevIndex;\n }\n }\n }\n return nextIndex;\n}\n\n/** For each cell index, gets the item index that occupies that cell */\nfunction createGridCellMap(sizes, cols, dense) {\n const cellMap = [];\n let startIndex = 0;\n sizes.forEach((_ref2, index) => {\n let {\n width,\n height\n } = _ref2;\n if (width > cols) {\n if (process.env.NODE_ENV !== \"production\") {\n throw new Error(\"[Floating UI]: Invalid grid - item width at index \" + index + \" is greater than grid columns\");\n }\n }\n let itemPlaced = false;\n if (dense) {\n startIndex = 0;\n }\n while (!itemPlaced) {\n const targetCells = [];\n for (let i = 0; i < width; i++) {\n for (let j = 0; j < height; j++) {\n targetCells.push(startIndex + i + j * cols);\n }\n }\n if (startIndex % cols + width <= cols && targetCells.every(cell => cellMap[cell] == null)) {\n targetCells.forEach(cell => {\n cellMap[cell] = index;\n });\n itemPlaced = true;\n } else {\n startIndex++;\n }\n }\n });\n\n // convert into a non-sparse array\n return [...cellMap];\n}\n\n/** Gets cell index of an item's corner or -1 when index is -1. */\nfunction getGridCellIndexOfCorner(index, sizes, cellMap, cols, corner) {\n if (index === -1) return -1;\n const firstCellIndex = cellMap.indexOf(index);\n const sizeItem = sizes[index];\n switch (corner) {\n case 'tl':\n return firstCellIndex;\n case 'tr':\n if (!sizeItem) {\n return firstCellIndex;\n }\n return firstCellIndex + sizeItem.width - 1;\n case 'bl':\n if (!sizeItem) {\n return firstCellIndex;\n }\n return firstCellIndex + (sizeItem.height - 1) * cols;\n case 'br':\n return cellMap.lastIndexOf(index);\n }\n}\n\n/** Gets all cell indices that correspond to the specified indices */\nfunction getGridCellIndices(indices, cellMap) {\n return cellMap.flatMap((index, cellIndex) => indices.includes(index) ? [cellIndex] : []);\n}\nfunction isListIndexDisabled(listRef, index, disabledIndices) {\n if (typeof disabledIndices === 'function') {\n return disabledIndices(index);\n } else if (disabledIndices) {\n return disabledIndices.includes(index);\n }\n const element = listRef.current[index];\n return element == null || element.hasAttribute('disabled') || element.getAttribute('aria-disabled') === 'true';\n}\n\nconst getTabbableOptions = () => ({\n getShadowRoot: true,\n displayCheck:\n // JSDOM does not support the `tabbable` library. To solve this we can\n // check if `ResizeObserver` is a real function (not polyfilled), which\n // determines if the current environment is JSDOM-like.\n typeof ResizeObserver === 'function' && ResizeObserver.toString().includes('[native code]') ? 'full' : 'none'\n});\nfunction getTabbableIn(container, dir) {\n const list = tabbable(container, getTabbableOptions());\n const len = list.length;\n if (len === 0) return;\n const active = activeElement(getDocument(container));\n const index = list.indexOf(active);\n const nextIndex = index === -1 ? dir === 1 ? 0 : len - 1 : index + dir;\n return list[nextIndex];\n}\nfunction getNextTabbable(referenceElement) {\n return getTabbableIn(getDocument(referenceElement).body, 1) || referenceElement;\n}\nfunction getPreviousTabbable(referenceElement) {\n return getTabbableIn(getDocument(referenceElement).body, -1) || referenceElement;\n}\nfunction isOutsideEvent(event, container) {\n const containerElement = container || event.currentTarget;\n const relatedTarget = event.relatedTarget;\n return !relatedTarget || !contains(containerElement, relatedTarget);\n}\nfunction disableFocusInside(container) {\n const tabbableElements = tabbable(container, getTabbableOptions());\n tabbableElements.forEach(element => {\n element.dataset.tabindex = element.getAttribute('tabindex') || '';\n element.setAttribute('tabindex', '-1');\n });\n}\nfunction enableFocusInside(container) {\n const elements = container.querySelectorAll('[data-tabindex]');\n elements.forEach(element => {\n const tabindex = element.dataset.tabindex;\n delete element.dataset.tabindex;\n if (tabindex) {\n element.setAttribute('tabindex', tabindex);\n } else {\n element.removeAttribute('tabindex');\n }\n });\n}\n\nexport { activeElement, contains, createGridCellMap, disableFocusInside, enableFocusInside, findNonDisabledListIndex, getDeepestNode, getDocument, getFloatingFocusElement, getGridCellIndexOfCorner, getGridCellIndices, getGridNavigatedIndex, getMaxListIndex, getMinListIndex, getNextTabbable, getNodeAncestors, getNodeChildren, getPlatform, getPreviousTabbable, getTabbableOptions, getTarget, getUserAgent, isAndroid, isDifferentGridRow, isEventTargetWithin, isIndexOutOfListBounds, isJSDOM, isListIndexDisabled, isMac, isMouseLikePointerType, isOutsideEvent, isReactEvent, isRootElement, isSafari, isTypeableCombobox, isTypeableElement, isVirtualClick, isVirtualPointerEvent, matchesFocusVisible, stopEvent, useEffectEvent, useLatestRef, index as useModernLayoutEffect };\n","import { getSideAxis, getAlignmentAxis, getAxisLength, getSide, getAlignment, evaluate, getPaddingObject, rectToClientRect, min, clamp, placements, getAlignmentSides, getOppositeAlignmentPlacement, getOppositePlacement, getExpandedPlacements, getOppositeAxisPlacements, sides, max, getOppositeAxis } from '@floating-ui/utils';\nexport { rectToClientRect } from '@floating-ui/utils';\n\nfunction computeCoordsFromPlacement(_ref, placement, rtl) {\n let {\n reference,\n floating\n } = _ref;\n const sideAxis = getSideAxis(placement);\n const alignmentAxis = getAlignmentAxis(placement);\n const alignLength = getAxisLength(alignmentAxis);\n const side = getSide(placement);\n const isVertical = sideAxis === 'y';\n const commonX = reference.x + reference.width / 2 - floating.width / 2;\n const commonY = reference.y + reference.height / 2 - floating.height / 2;\n const commonAlign = reference[alignLength] / 2 - floating[alignLength] / 2;\n let coords;\n switch (side) {\n case 'top':\n coords = {\n x: commonX,\n y: reference.y - floating.height\n };\n break;\n case 'bottom':\n coords = {\n x: commonX,\n y: reference.y + reference.height\n };\n break;\n case 'right':\n coords = {\n x: reference.x + reference.width,\n y: commonY\n };\n break;\n case 'left':\n coords = {\n x: reference.x - floating.width,\n y: commonY\n };\n break;\n default:\n coords = {\n x: reference.x,\n y: reference.y\n };\n }\n const alignment = getAlignment(placement);\n if (alignment) {\n coords[alignmentAxis] += commonAlign * (alignment === 'end' ? 1 : -1) * (rtl && isVertical ? -1 : 1);\n }\n return coords;\n}\n\n/**\n * Resolves with an object of overflow side offsets that determine how much the\n * element is overflowing a given clipping boundary on each side.\n * - positive = overflowing the boundary by that number of pixels\n * - negative = how many pixels left before it will overflow\n * - 0 = lies flush with the boundary\n * @see https://floating-ui.com/docs/detectOverflow\n */\nasync function detectOverflow(state, options) {\n var _await$platform$isEle;\n if (options === void 0) {\n options = {};\n }\n const {\n x,\n y,\n platform,\n rects,\n elements,\n strategy\n } = state;\n const {\n boundary = 'clippingAncestors',\n rootBoundary = 'viewport',\n elementContext = 'floating',\n altBoundary = false,\n padding = 0\n } = evaluate(options, state);\n const paddingObject = getPaddingObject(padding);\n const altContext = elementContext === 'floating' ? 'reference' : 'floating';\n const element = elements[altBoundary ? altContext : elementContext];\n const clippingClientRect = rectToClientRect(await platform.getClippingRect({\n element: ((_await$platform$isEle = await (platform.isElement == null ? void 0 : platform.isElement(element))) != null ? _await$platform$isEle : true) ? element : element.contextElement || (await (platform.getDocumentElement == null ? void 0 : platform.getDocumentElement(elements.floating))),\n boundary,\n rootBoundary,\n strategy\n }));\n const rect = elementContext === 'floating' ? {\n x,\n y,\n width: rects.floating.width,\n height: rects.floating.height\n } : rects.reference;\n const offsetParent = await (platform.getOffsetParent == null ? void 0 : platform.getOffsetParent(elements.floating));\n const offsetScale = (await (platform.isElement == null ? void 0 : platform.isElement(offsetParent))) && (await (platform.getScale == null ? void 0 : platform.getScale(offsetParent))) || {\n x: 1,\n y: 1\n };\n const elementClientRect = rectToClientRect(platform.convertOffsetParentRelativeRectToViewportRelativeRect ? await platform.convertOffsetParentRelativeRectToViewportRelativeRect({\n elements,\n rect,\n offsetParent,\n strategy\n }) : rect);\n return {\n top: (clippingClientRect.top - elementClientRect.top + paddingObject.top) / offsetScale.y,\n bottom: (elementClientRect.bottom - clippingClientRect.bottom + paddingObject.bottom) / offsetScale.y,\n left: (clippingClientRect.left - elementClientRect.left + paddingObject.left) / offsetScale.x,\n right: (elementClientRect.right - clippingClientRect.right + paddingObject.right) / offsetScale.x\n };\n}\n\n// Maximum number of resets that can occur before bailing to avoid infinite reset loops.\nconst MAX_RESET_COUNT = 50;\n\n/**\n * Computes the `x` and `y` coordinates that will place the floating element\n * next to a given reference element.\n *\n * This export does not have any `platform` interface logic. You will need to\n * write one for the platform you are using Floating UI with.\n */\nconst computePosition = async (reference, floating, config) => {\n const {\n placement = 'bottom',\n strategy = 'absolute',\n middleware = [],\n platform\n } = config;\n const platformWithDetectOverflow = platform.detectOverflow ? platform : {\n ...platform,\n detectOverflow\n };\n const rtl = await (platform.isRTL == null ? void 0 : platform.isRTL(floating));\n let rects = await platform.getElementRects({\n reference,\n floating,\n strategy\n });\n let {\n x,\n y\n } = computeCoordsFromPlacement(rects, placement, rtl);\n let statefulPlacement = placement;\n let resetCount = 0;\n const middlewareData = {};\n for (let i = 0; i < middleware.length; i++) {\n const currentMiddleware = middleware[i];\n if (!currentMiddleware) {\n continue;\n }\n const {\n name,\n fn\n } = currentMiddleware;\n const {\n x: nextX,\n y: nextY,\n data,\n reset\n } = await fn({\n x,\n y,\n initialPlacement: placement,\n placement: statefulPlacement,\n strategy,\n middlewareData,\n rects,\n platform: platformWithDetectOverflow,\n elements: {\n reference,\n floating\n }\n });\n x = nextX != null ? nextX : x;\n y = nextY != null ? nextY : y;\n middlewareData[name] = {\n ...middlewareData[name],\n ...data\n };\n if (reset && resetCount < MAX_RESET_COUNT) {\n resetCount++;\n if (typeof reset === 'object') {\n if (reset.placement) {\n statefulPlacement = reset.placement;\n }\n if (reset.rects) {\n rects = reset.rects === true ? await platform.getElementRects({\n reference,\n floating,\n strategy\n }) : reset.rects;\n }\n ({\n x,\n y\n } = computeCoordsFromPlacement(rects, statefulPlacement, rtl));\n }\n i = -1;\n }\n }\n return {\n x,\n y,\n placement: statefulPlacement,\n strategy,\n middlewareData\n };\n};\n\n/**\n * Provides data to position an inner element of the floating element so that it\n * appears centered to the reference element.\n * @see https://floating-ui.com/docs/arrow\n */\nconst arrow = options => ({\n name: 'arrow',\n options,\n async fn(state) {\n const {\n x,\n y,\n placement,\n rects,\n platform,\n elements,\n middlewareData\n } = state;\n // Since `element` is required, we don't Partial<> the type.\n const {\n element,\n padding = 0\n } = evaluate(options, state) || {};\n if (element == null) {\n return {};\n }\n const paddingObject = getPaddingObject(padding);\n const coords = {\n x,\n y\n };\n const axis = getAlignmentAxis(placement);\n const length = getAxisLength(axis);\n const arrowDimensions = await platform.getDimensions(element);\n const isYAxis = axis === 'y';\n const minProp = isYAxis ? 'top' : 'left';\n const maxProp = isYAxis ? 'bottom' : 'right';\n const clientProp = isYAxis ? 'clientHeight' : 'clientWidth';\n const endDiff = rects.reference[length] + rects.reference[axis] - coords[axis] - rects.floating[length];\n const startDiff = coords[axis] - rects.reference[axis];\n const arrowOffsetParent = await (platform.getOffsetParent == null ? void 0 : platform.getOffsetParent(element));\n let clientSize = arrowOffsetParent ? arrowOffsetParent[clientProp] : 0;\n\n // DOM platform can return `window` as the `offsetParent`.\n if (!clientSize || !(await (platform.isElement == null ? void 0 : platform.isElement(arrowOffsetParent)))) {\n clientSize = elements.floating[clientProp] || rects.floating[length];\n }\n const centerToReference = endDiff / 2 - startDiff / 2;\n\n // If the padding is large enough that it causes the arrow to no longer be\n // centered, modify the padding so that it is centered.\n const largestPossiblePadding = clientSize / 2 - arrowDimensions[length] / 2 - 1;\n const minPadding = min(paddingObject[minProp], largestPossiblePadding);\n const maxPadding = min(paddingObject[maxProp], largestPossiblePadding);\n\n // Make sure the arrow doesn't overflow the floating element if the center\n // point is outside the floating element's bounds.\n const max = clientSize - arrowDimensions[length] - maxPadding;\n const center = clientSize / 2 - arrowDimensions[length] / 2 + centerToReference;\n const offset = clamp(minPadding, center, max);\n\n // If the reference is small enough that the arrow's padding causes it to\n // to point to nothing for an aligned placement, adjust the offset of the\n // floating element itself. To ensure `shift()` continues to take action,\n // a single reset is performed when this is true.\n const shouldAddOffset = !middlewareData.arrow && getAlignment(placement) != null && center !== offset && rects.reference[length] / 2 - (center < minPadding ? minPadding : maxPadding) - arrowDimensions[length] / 2 < 0;\n const alignmentOffset = shouldAddOffset ? center < minPadding ? center - minPadding : center - max : 0;\n return {\n [axis]: coords[axis] + alignmentOffset,\n data: {\n [axis]: offset,\n centerOffset: center - offset - alignmentOffset,\n ...(shouldAddOffset && {\n alignmentOffset\n })\n },\n reset: shouldAddOffset\n };\n }\n});\n\nfunction getPlacementList(alignment, autoAlignment, allowedPlacements) {\n const allowedPlacementsSortedByAlignment = alignment ? [...allowedPlacements.filter(placement => getAlignment(placement) === alignment), ...allowedPlacements.filter(placement => getAlignment(placement) !== alignment)] : allowedPlacements.filter(placement => getSide(placement) === placement);\n return allowedPlacementsSortedByAlignment.filter(placement => {\n if (alignment) {\n return getAlignment(placement) === alignment || (autoAlignment ? getOppositeAlignmentPlacement(placement) !== placement : false);\n }\n return true;\n });\n}\n/**\n * Optimizes the visibility of the floating element by choosing the placement\n * that has the most space available automatically, without needing to specify a\n * preferred placement. Alternative to `flip`.\n * @see https://floating-ui.com/docs/autoPlacement\n */\nconst autoPlacement = function (options) {\n if (options === void 0) {\n options = {};\n }\n return {\n name: 'autoPlacement',\n options,\n async fn(state) {\n var _middlewareData$autoP, _middlewareData$autoP2, _placementsThatFitOnE;\n const {\n rects,\n middlewareData,\n placement,\n platform,\n elements\n } = state;\n const {\n crossAxis = false,\n alignment,\n allowedPlacements = placements,\n autoAlignment = true,\n ...detectOverflowOptions\n } = evaluate(options, state);\n const placements$1 = alignment !== undefined || allowedPlacements === placements ? getPlacementList(alignment || null, autoAlignment, allowedPlacements) : allowedPlacements;\n const currentIndex = ((_middlewareData$autoP = middlewareData.autoPlacement) == null ? void 0 : _middlewareData$autoP.index) || 0;\n const currentPlacement = placements$1[currentIndex];\n if (currentPlacement == null) {\n return {};\n }\n\n // Make `computeCoords` start from the right place.\n if (placement !== currentPlacement) {\n return {\n reset: {\n placement: placements$1[0]\n }\n };\n }\n const overflow = await platform.detectOverflow(state, detectOverflowOptions);\n const alignmentSides = getAlignmentSides(currentPlacement, rects, await (platform.isRTL == null ? void 0 : platform.isRTL(elements.floating)));\n const currentOverflows = [overflow[getSide(currentPlacement)], overflow[alignmentSides[0]], overflow[alignmentSides[1]]];\n const allOverflows = [...(((_middlewareData$autoP2 = middlewareData.autoPlacement) == null ? void 0 : _middlewareData$autoP2.overflows) || []), {\n placement: currentPlacement,\n overflows: currentOverflows\n }];\n const nextPlacement = placements$1[currentIndex + 1];\n\n // There are more placements to check.\n if (nextPlacement) {\n return {\n data: {\n index: currentIndex + 1,\n overflows: allOverflows\n },\n reset: {\n placement: nextPlacement\n }\n };\n }\n const placementsSortedByMostSpace = allOverflows.map(d => {\n const alignment = getAlignment(d.placement);\n return [d.placement, alignment && crossAxis ?\n // Check along the mainAxis and main crossAxis side.\n d.overflows.slice(0, 2).reduce((acc, v) => acc + v, 0) :\n // Check only the mainAxis.\n d.overflows[0], d.overflows];\n }).sort((a, b) => a[1] - b[1]);\n const placementsThatFitOnEachSide = placementsSortedByMostSpace.filter(d => d[2].slice(0,\n // Aligned placements should not check their opposite crossAxis\n // side.\n getAlignment(d[0]) ? 2 : 3).every(v => v <= 0));\n const resetPlacement = ((_placementsThatFitOnE = placementsThatFitOnEachSide[0]) == null ? void 0 : _placementsThatFitOnE[0]) || placementsSortedByMostSpace[0][0];\n if (resetPlacement !== placement) {\n return {\n data: {\n index: currentIndex + 1,\n overflows: allOverflows\n },\n reset: {\n placement: resetPlacement\n }\n };\n }\n return {};\n }\n };\n};\n\n/**\n * Optimizes the visibility of the floating element by flipping the `placement`\n * in order to keep it in view when the preferred placement(s) will overflow the\n * clipping boundary. Alternative to `autoPlacement`.\n * @see https://floating-ui.com/docs/flip\n */\nconst flip = function (options) {\n if (options === void 0) {\n options = {};\n }\n return {\n name: 'flip',\n options,\n async fn(state) {\n var _middlewareData$arrow, _middlewareData$flip;\n const {\n placement,\n middlewareData,\n rects,\n initialPlacement,\n platform,\n elements\n } = state;\n const {\n mainAxis: checkMainAxis = true,\n crossAxis: checkCrossAxis = true,\n fallbackPlacements: specifiedFallbackPlacements,\n fallbackStrategy = 'bestFit',\n fallbackAxisSideDirection = 'none',\n flipAlignment = true,\n ...detectOverflowOptions\n } = evaluate(options, state);\n\n // If a reset by the arrow was caused due to an alignment offset being\n // added, we should skip any logic now since `flip()` has already done its\n // work.\n // https://github.com/floating-ui/floating-ui/issues/2549#issuecomment-1719601643\n if ((_middlewareData$arrow = middlewareData.arrow) != null && _middlewareData$arrow.alignmentOffset) {\n return {};\n }\n const side = getSide(placement);\n const initialSideAxis = getSideAxis(initialPlacement);\n const isBasePlacement = getSide(initialPlacement) === initialPlacement;\n const rtl = await (platform.isRTL == null ? void 0 : platform.isRTL(elements.floating));\n const fallbackPlacements = specifiedFallbackPlacements || (isBasePlacement || !flipAlignment ? [getOppositePlacement(initialPlacement)] : getExpandedPlacements(initialPlacement));\n const hasFallbackAxisSideDirection = fallbackAxisSideDirection !== 'none';\n if (!specifiedFallbackPlacements && hasFallbackAxisSideDirection) {\n fallbackPlacements.push(...getOppositeAxisPlacements(initialPlacement, flipAlignment, fallbackAxisSideDirection, rtl));\n }\n const placements = [initialPlacement, ...fallbackPlacements];\n const overflow = await platform.detectOverflow(state, detectOverflowOptions);\n const overflows = [];\n let overflowsData = ((_middlewareData$flip = middlewareData.flip) == null ? void 0 : _middlewareData$flip.overflows) || [];\n if (checkMainAxis) {\n overflows.push(overflow[side]);\n }\n if (checkCrossAxis) {\n const sides = getAlignmentSides(placement, rects, rtl);\n overflows.push(overflow[sides[0]], overflow[sides[1]]);\n }\n overflowsData = [...overflowsData, {\n placement,\n overflows\n }];\n\n // One or more sides is overflowing.\n if (!overflows.every(side => side <= 0)) {\n var _middlewareData$flip2, _overflowsData$filter;\n const nextIndex = (((_middlewareData$flip2 = middlewareData.flip) == null ? void 0 : _middlewareData$flip2.index) || 0) + 1;\n const nextPlacement = placements[nextIndex];\n if (nextPlacement) {\n const ignoreCrossAxisOverflow = checkCrossAxis === 'alignment' ? initialSideAxis !== getSideAxis(nextPlacement) : false;\n if (!ignoreCrossAxisOverflow ||\n // We leave the current main axis only if every placement on that axis\n // overflows the main axis.\n overflowsData.every(d => getSideAxis(d.placement) === initialSideAxis ? d.overflows[0] > 0 : true)) {\n // Try next placement and re-run the lifecycle.\n return {\n data: {\n index: nextIndex,\n overflows: overflowsData\n },\n reset: {\n placement: nextPlacement\n }\n };\n }\n }\n\n // First, find the candidates that fit on the mainAxis side of overflow,\n // then find the placement that fits the best on the main crossAxis side.\n let resetPlacement = (_overflowsData$filter = overflowsData.filter(d => d.overflows[0] <= 0).sort((a, b) => a.overflows[1] - b.overflows[1])[0]) == null ? void 0 : _overflowsData$filter.placement;\n\n // Otherwise fallback.\n if (!resetPlacement) {\n switch (fallbackStrategy) {\n case 'bestFit':\n {\n var _overflowsData$filter2;\n const placement = (_overflowsData$filter2 = overflowsData.filter(d => {\n if (hasFallbackAxisSideDirection) {\n const currentSideAxis = getSideAxis(d.placement);\n return currentSideAxis === initialSideAxis ||\n // Create a bias to the `y` side axis due to horizontal\n // reading directions favoring greater width.\n currentSideAxis === 'y';\n }\n return true;\n }).map(d => [d.placement, d.overflows.filter(overflow => overflow > 0).reduce((acc, overflow) => acc + overflow, 0)]).sort((a, b) => a[1] - b[1])[0]) == null ? void 0 : _overflowsData$filter2[0];\n if (placement) {\n resetPlacement = placement;\n }\n break;\n }\n case 'initialPlacement':\n resetPlacement = initialPlacement;\n break;\n }\n }\n if (placement !== resetPlacement) {\n return {\n reset: {\n placement: resetPlacement\n }\n };\n }\n }\n return {};\n }\n };\n};\n\nfunction getSideOffsets(overflow, rect) {\n return {\n top: overflow.top - rect.height,\n right: overflow.right - rect.width,\n bottom: overflow.bottom - rect.height,\n left: overflow.left - rect.width\n };\n}\nfunction isAnySideFullyClipped(overflow) {\n return sides.some(side => overflow[side] >= 0);\n}\n/**\n * Provides data to hide the floating element in applicable situations, such as\n * when it is not in the same clipping context as the reference element.\n * @see https://floating-ui.com/docs/hide\n */\nconst hide = function (options) {\n if (options === void 0) {\n options = {};\n }\n return {\n name: 'hide',\n options,\n async fn(state) {\n const {\n rects,\n platform\n } = state;\n const {\n strategy = 'referenceHidden',\n ...detectOverflowOptions\n } = evaluate(options, state);\n switch (strategy) {\n case 'referenceHidden':\n {\n const overflow = await platform.detectOverflow(state, {\n ...detectOverflowOptions,\n elementContext: 'reference'\n });\n const offsets = getSideOffsets(overflow, rects.reference);\n return {\n data: {\n referenceHiddenOffsets: offsets,\n referenceHidden: isAnySideFullyClipped(offsets)\n }\n };\n }\n case 'escaped':\n {\n const overflow = await platform.detectOverflow(state, {\n ...detectOverflowOptions,\n altBoundary: true\n });\n const offsets = getSideOffsets(overflow, rects.floating);\n return {\n data: {\n escapedOffsets: offsets,\n escaped: isAnySideFullyClipped(offsets)\n }\n };\n }\n default:\n {\n return {};\n }\n }\n }\n };\n};\n\nfunction getBoundingRect(rects) {\n const minX = min(...rects.map(rect => rect.left));\n const minY = min(...rects.map(rect => rect.top));\n const maxX = max(...rects.map(rect => rect.right));\n const maxY = max(...rects.map(rect => rect.bottom));\n return {\n x: minX,\n y: minY,\n width: maxX - minX,\n height: maxY - minY\n };\n}\nfunction getRectsByLine(rects) {\n const sortedRects = rects.slice().sort((a, b) => a.y - b.y);\n const groups = [];\n let prevRect = null;\n for (let i = 0; i < sortedRects.length; i++) {\n const rect = sortedRects[i];\n if (!prevRect || rect.y - prevRect.y > prevRect.height / 2) {\n groups.push([rect]);\n } else {\n groups[groups.length - 1].push(rect);\n }\n prevRect = rect;\n }\n return groups.map(rect => rectToClientRect(getBoundingRect(rect)));\n}\n/**\n * Provides improved positioning for inline reference elements that can span\n * over multiple lines, such as hyperlinks or range selections.\n * @see https://floating-ui.com/docs/inline\n */\nconst inline = function (options) {\n if (options === void 0) {\n options = {};\n }\n return {\n name: 'inline',\n options,\n async fn(state) {\n const {\n placement,\n elements,\n rects,\n platform,\n strategy\n } = state;\n // A MouseEvent's client{X,Y} coords can be up to 2 pixels off a\n // ClientRect's bounds, despite the event listener being triggered. A\n // padding of 2 seems to handle this issue.\n const {\n padding = 2,\n x,\n y\n } = evaluate(options, state);\n const nativeClientRects = Array.from((await (platform.getClientRects == null ? void 0 : platform.getClientRects(elements.reference))) || []);\n\n // No rects (e.g. a hidden or detached reference, or a collapsed range) —\n // keep the existing reference rect rather than resetting to an invalid\n // one with non-finite values.\n if (!nativeClientRects.length) {\n return {};\n }\n const clientRects = getRectsByLine(nativeClientRects);\n const fallback = rectToClientRect(getBoundingRect(nativeClientRects));\n const paddingObject = getPaddingObject(padding);\n function getBoundingClientRect() {\n // There are two rects and they are disjoined.\n if (clientRects.length === 2 && (clientRects[0].left > clientRects[1].right || clientRects[1].left > clientRects[0].right) && x != null && y != null) {\n // Find the first rect in which the point is fully inside.\n return clientRects.find(rect => x > rect.left - paddingObject.left && x < rect.right + paddingObject.right && y > rect.top - paddingObject.top && y < rect.bottom + paddingObject.bottom) || fallback;\n }\n\n // There are 2 or more connected rects.\n if (clientRects.length >= 2) {\n if (getSideAxis(placement) === 'y') {\n const firstRect = clientRects[0];\n const lastRect = clientRects[clientRects.length - 1];\n const isTop = getSide(placement) === 'top';\n const top = firstRect.top;\n const bottom = lastRect.bottom;\n const left = isTop ? firstRect.left : lastRect.left;\n const right = isTop ? firstRect.right : lastRect.right;\n return rectToClientRect({\n x: left,\n y: top,\n width: right - left,\n height: bottom - top\n });\n }\n const isLeftSide = getSide(placement) === 'left';\n const maxRight = max(...clientRects.map(rect => rect.right));\n const minLeft = min(...clientRects.map(rect => rect.left));\n const measureRects = clientRects.filter(rect => isLeftSide ? rect.left === minLeft : rect.right === maxRight);\n const top = measureRects[0].top;\n const bottom = measureRects[measureRects.length - 1].bottom;\n return rectToClientRect({\n x: minLeft,\n y: top,\n width: maxRight - minLeft,\n height: bottom - top\n });\n }\n return fallback;\n }\n const resetRects = await platform.getElementRects({\n reference: {\n getBoundingClientRect\n },\n floating: elements.floating,\n strategy\n });\n if (rects.reference.x !== resetRects.reference.x || rects.reference.y !== resetRects.reference.y || rects.reference.width !== resetRects.reference.width || rects.reference.height !== resetRects.reference.height) {\n return {\n reset: {\n rects: resetRects\n }\n };\n }\n return {};\n }\n };\n};\n\nconst originSides = /*#__PURE__*/new Set(['left', 'top']);\n\n// For type backwards-compatibility, the `OffsetOptions` type was also\n// Derivable.\n\nasync function convertValueToCoords(state, options) {\n const {\n placement,\n platform,\n elements\n } = state;\n const rtl = await (platform.isRTL == null ? void 0 : platform.isRTL(elements.floating));\n const side = getSide(placement);\n const alignment = getAlignment(placement);\n const isVertical = getSideAxis(placement) === 'y';\n const mainAxisMulti = originSides.has(side) ? -1 : 1;\n const crossAxisMulti = rtl && isVertical ? -1 : 1;\n const rawValue = evaluate(options, state);\n\n // eslint-disable-next-line prefer-const\n let {\n mainAxis,\n crossAxis,\n alignmentAxis\n } = typeof rawValue === 'number' ? {\n mainAxis: rawValue,\n crossAxis: 0,\n alignmentAxis: null\n } : {\n mainAxis: rawValue.mainAxis || 0,\n crossAxis: rawValue.crossAxis || 0,\n alignmentAxis: rawValue.alignmentAxis\n };\n if (alignment && typeof alignmentAxis === 'number') {\n crossAxis = alignment === 'end' ? alignmentAxis * -1 : alignmentAxis;\n }\n return isVertical ? {\n x: crossAxis * crossAxisMulti,\n y: mainAxis * mainAxisMulti\n } : {\n x: mainAxis * mainAxisMulti,\n y: crossAxis * crossAxisMulti\n };\n}\n\n/**\n * Modifies the placement by translating the floating element along the\n * specified axes.\n * A number (shorthand for `mainAxis` or distance), or an axes configuration\n * object may be passed.\n * @see https://floating-ui.com/docs/offset\n */\nconst offset = function (options) {\n if (options === void 0) {\n options = 0;\n }\n return {\n name: 'offset',\n options,\n async fn(state) {\n var _middlewareData$offse, _middlewareData$arrow;\n const {\n x,\n y,\n placement,\n middlewareData\n } = state;\n const diffCoords = await convertValueToCoords(state, options);\n\n // If the placement is the same and the arrow caused an alignment offset\n // then we don't need to change the positioning coordinates.\n if (placement === ((_middlewareData$offse = middlewareData.offset) == null ? void 0 : _middlewareData$offse.placement) && (_middlewareData$arrow = middlewareData.arrow) != null && _middlewareData$arrow.alignmentOffset) {\n return {};\n }\n return {\n x: x + diffCoords.x,\n y: y + diffCoords.y,\n data: {\n ...diffCoords,\n placement\n }\n };\n }\n };\n};\n\n/**\n * Optimizes the visibility of the floating element by shifting it in order to\n * keep it in view when it will overflow the clipping boundary.\n * @see https://floating-ui.com/docs/shift\n */\nconst shift = function (options) {\n if (options === void 0) {\n options = {};\n }\n return {\n name: 'shift',\n options,\n async fn(state) {\n const {\n x,\n y,\n placement,\n platform\n } = state;\n const {\n mainAxis: checkMainAxis = true,\n crossAxis: checkCrossAxis = false,\n limiter = {\n fn: _ref => {\n let {\n x,\n y\n } = _ref;\n return {\n x,\n y\n };\n }\n },\n ...detectOverflowOptions\n } = evaluate(options, state);\n const coords = {\n x,\n y\n };\n const overflow = await platform.detectOverflow(state, detectOverflowOptions);\n const crossAxis = getSideAxis(placement);\n const mainAxis = getOppositeAxis(crossAxis);\n let mainAxisCoord = coords[mainAxis];\n let crossAxisCoord = coords[crossAxis];\n const clampCoord = (axis, coord) => clamp(coord + overflow[axis === 'y' ? 'top' : 'left'], coord, coord - overflow[axis === 'y' ? 'bottom' : 'right']);\n if (checkMainAxis) {\n mainAxisCoord = clampCoord(mainAxis, mainAxisCoord);\n }\n if (checkCrossAxis) {\n crossAxisCoord = clampCoord(crossAxis, crossAxisCoord);\n }\n const limitedCoords = limiter.fn({\n ...state,\n [mainAxis]: mainAxisCoord,\n [crossAxis]: crossAxisCoord\n });\n return {\n ...limitedCoords,\n data: {\n x: limitedCoords.x - x,\n y: limitedCoords.y - y,\n enabled: {\n [mainAxis]: checkMainAxis,\n [crossAxis]: checkCrossAxis\n }\n }\n };\n }\n };\n};\n/**\n * Built-in `limiter` that will stop `shift()` at a certain point.\n */\nconst limitShift = function (options) {\n if (options === void 0) {\n options = {};\n }\n return {\n options,\n fn(state) {\n var _rawOffset$mainAxis, _rawOffset$crossAxis;\n const {\n x,\n y,\n placement,\n rects,\n middlewareData\n } = state;\n const {\n offset = 0,\n mainAxis: checkMainAxis = true,\n crossAxis: checkCrossAxis = true\n } = evaluate(options, state);\n const coords = {\n x,\n y\n };\n const crossAxis = getSideAxis(placement);\n const mainAxis = getOppositeAxis(crossAxis);\n let mainAxisCoord = coords[mainAxis];\n let crossAxisCoord = coords[crossAxis];\n const rawOffset = evaluate(offset, state);\n const computedOffset = typeof rawOffset === 'number' ? {\n mainAxis: rawOffset,\n crossAxis: 0\n } : {\n mainAxis: (_rawOffset$mainAxis = rawOffset.mainAxis) != null ? _rawOffset$mainAxis : 0,\n crossAxis: (_rawOffset$crossAxis = rawOffset.crossAxis) != null ? _rawOffset$crossAxis : 0\n };\n if (checkMainAxis) {\n const len = mainAxis === 'y' ? 'height' : 'width';\n const limitMin = rects.reference[mainAxis] - rects.floating[len] + computedOffset.mainAxis;\n const limitMax = rects.reference[mainAxis] + rects.reference[len] - computedOffset.mainAxis;\n if (mainAxisCoord < limitMin) {\n mainAxisCoord = limitMin;\n } else if (mainAxisCoord > limitMax) {\n mainAxisCoord = limitMax;\n }\n }\n if (checkCrossAxis) {\n var _middlewareData$offse, _middlewareData$offse2;\n const len = mainAxis === 'y' ? 'width' : 'height';\n const isOriginSide = originSides.has(getSide(placement));\n const limitMin = rects.reference[crossAxis] - rects.floating[len] + (isOriginSide ? ((_middlewareData$offse = middlewareData.offset) == null ? void 0 : _middlewareData$offse[crossAxis]) || 0 : 0) + (isOriginSide ? 0 : computedOffset.crossAxis);\n const limitMax = rects.reference[crossAxis] + rects.reference[len] + (isOriginSide ? 0 : ((_middlewareData$offse2 = middlewareData.offset) == null ? void 0 : _middlewareData$offse2[crossAxis]) || 0) - (isOriginSide ? computedOffset.crossAxis : 0);\n if (crossAxisCoord < limitMin) {\n crossAxisCoord = limitMin;\n } else if (crossAxisCoord > limitMax) {\n crossAxisCoord = limitMax;\n }\n }\n return {\n [mainAxis]: mainAxisCoord,\n [crossAxis]: crossAxisCoord\n };\n }\n };\n};\n\n// Method syntax keeps callback parameters bivariant, but expressing the\n// explicit `| undefined` required by `exactOptionalPropertyTypes` needs\n// property syntax, which is contravariant under `strictFunctionTypes`.\n// Extracting the function from a method position restores that bivariance so\n// consumers can still assign callbacks with narrower parameter types.\n\n/**\n * Provides data that allows you to change the size of the floating element —\n * for instance, prevent it from overflowing the clipping boundary or match the\n * width of the reference element.\n * @see https://floating-ui.com/docs/size\n */\nconst size = function (options) {\n if (options === void 0) {\n options = {};\n }\n return {\n name: 'size',\n options,\n async fn(state) {\n const {\n placement,\n rects,\n platform,\n elements\n } = state;\n const {\n apply = () => {},\n ...detectOverflowOptions\n } = evaluate(options, state);\n const overflow = await platform.detectOverflow(state, detectOverflowOptions);\n const side = getSide(placement);\n const alignment = getAlignment(placement);\n const isYAxis = getSideAxis(placement) === 'y';\n const {\n width,\n height\n } = rects.floating;\n let heightSide;\n let widthSide;\n if (side === 'top' || side === 'bottom') {\n heightSide = side;\n widthSide = alignment === ((await (platform.isRTL == null ? void 0 : platform.isRTL(elements.floating))) ? 'start' : 'end') ? 'left' : 'right';\n } else {\n widthSide = side;\n heightSide = alignment === 'end' ? 'top' : 'bottom';\n }\n const maximumClippingHeight = height - overflow.top - overflow.bottom;\n const maximumClippingWidth = width - overflow.left - overflow.right;\n const overflowAvailableHeight = min(height - overflow[heightSide], maximumClippingHeight);\n const overflowAvailableWidth = min(width - overflow[widthSide], maximumClippingWidth);\n const shiftData = state.middlewareData.shift;\n const noShift = !shiftData;\n let availableHeight = overflowAvailableHeight;\n let availableWidth = overflowAvailableWidth;\n if (shiftData != null && shiftData.enabled.x) {\n availableWidth = maximumClippingWidth;\n }\n if (shiftData != null && shiftData.enabled.y) {\n availableHeight = maximumClippingHeight;\n }\n if (noShift && !alignment) {\n if (isYAxis) {\n availableWidth = width - 2 * max(overflow.left, overflow.right);\n } else {\n availableHeight = height - 2 * max(overflow.top, overflow.bottom);\n }\n }\n await apply({\n ...state,\n availableWidth,\n availableHeight\n });\n const nextDimensions = await platform.getDimensions(elements.floating);\n if (width !== nextDimensions.width || height !== nextDimensions.height) {\n return {\n reset: {\n rects: true\n }\n };\n }\n return {};\n }\n };\n};\n\nexport { arrow, autoPlacement, computePosition, detectOverflow, flip, hide, inline, limitShift, offset, shift, size };\n","import { rectToClientRect, arrow as arrow$1, autoPlacement as autoPlacement$1, detectOverflow as detectOverflow$1, flip as flip$1, hide as hide$1, inline as inline$1, limitShift as limitShift$1, offset as offset$1, shift as shift$1, size as size$1, computePosition as computePosition$1 } from '@floating-ui/core';\nimport { round, createCoords, max, min, floor } from '@floating-ui/utils';\nimport { getComputedStyle as getComputedStyle$1, isHTMLElement, isElement, getWindow, isWebKit, getFrameElement, getNodeScroll, getDocumentElement, isTopLayer, getNodeName, isOverflowElement, getOverflowAncestors, getParentNode, isLastTraversableNode, isContainingBlock, isTableElement, getContainingBlock } from '@floating-ui/utils/dom';\nexport { getOverflowAncestors } from '@floating-ui/utils/dom';\n\nfunction getCssDimensions(element) {\n const css = getComputedStyle$1(element);\n // In testing environments, the `width` and `height` properties are empty\n // strings for SVG elements, returning NaN. Fallback to `0` in this case.\n let width = parseFloat(css.width) || 0;\n let height = parseFloat(css.height) || 0;\n const hasOffset = isHTMLElement(element);\n const offsetWidth = hasOffset ? element.offsetWidth : width;\n const offsetHeight = hasOffset ? element.offsetHeight : height;\n const shouldFallback = round(width) !== offsetWidth || round(height) !== offsetHeight;\n if (shouldFallback) {\n width = offsetWidth;\n height = offsetHeight;\n }\n return {\n width,\n height,\n $: shouldFallback\n };\n}\n\nfunction unwrapElement(element) {\n return !isElement(element) ? element.contextElement : element;\n}\n\nfunction getScale(element) {\n const domElement = unwrapElement(element);\n if (!isHTMLElement(domElement)) {\n return createCoords(1);\n }\n const rect = domElement.getBoundingClientRect();\n const {\n width,\n height,\n $\n } = getCssDimensions(domElement);\n let x = ($ ? round(rect.width) : rect.width) / width;\n let y = ($ ? round(rect.height) : rect.height) / height;\n\n // 0, NaN, or Infinity should always fallback to 1.\n\n if (!x || !Number.isFinite(x)) {\n x = 1;\n }\n if (!y || !Number.isFinite(y)) {\n y = 1;\n }\n return {\n x,\n y\n };\n}\n\nconst noOffsets = /*#__PURE__*/createCoords(0);\nfunction getVisualOffsets(element) {\n const win = getWindow(element);\n if (!isWebKit() || !win.visualViewport) {\n return noOffsets;\n }\n return {\n x: win.visualViewport.offsetLeft,\n y: win.visualViewport.offsetTop\n };\n}\nfunction shouldAddVisualOffsets(element, isFixed, floatingOffsetParent) {\n if (isFixed === void 0) {\n isFixed = false;\n }\n return !!floatingOffsetParent && isFixed && floatingOffsetParent === getWindow(element);\n}\n\nfunction getBoundingClientRect(element, includeScale, isFixedStrategy, offsetParent) {\n if (includeScale === void 0) {\n includeScale = false;\n }\n if (isFixedStrategy === void 0) {\n isFixedStrategy = false;\n }\n const clientRect = element.getBoundingClientRect();\n const domElement = unwrapElement(element);\n let scale = createCoords(1);\n if (includeScale) {\n if (offsetParent) {\n if (isElement(offsetParent)) {\n scale = getScale(offsetParent);\n }\n } else {\n scale = getScale(element);\n }\n }\n const visualOffsets = shouldAddVisualOffsets(domElement, isFixedStrategy, offsetParent) ? getVisualOffsets(domElement) : createCoords(0);\n let x = (clientRect.left + visualOffsets.x) / scale.x;\n let y = (clientRect.top + visualOffsets.y) / scale.y;\n let width = clientRect.width / scale.x;\n let height = clientRect.height / scale.y;\n if (domElement && offsetParent) {\n const win = getWindow(domElement);\n const offsetWin = isElement(offsetParent) ? getWindow(offsetParent) : offsetParent;\n let currentWin = win;\n let currentIFrame = getFrameElement(currentWin);\n while (currentIFrame && offsetWin !== currentWin) {\n const iframeScale = getScale(currentIFrame);\n const iframeRect = currentIFrame.getBoundingClientRect();\n const css = getComputedStyle$1(currentIFrame);\n const left = iframeRect.left + (currentIFrame.clientLeft + parseFloat(css.paddingLeft)) * iframeScale.x;\n const top = iframeRect.top + (currentIFrame.clientTop + parseFloat(css.paddingTop)) * iframeScale.y;\n x *= iframeScale.x;\n y *= iframeScale.y;\n width *= iframeScale.x;\n height *= iframeScale.y;\n x += left;\n y += top;\n currentWin = getWindow(currentIFrame);\n currentIFrame = getFrameElement(currentWin);\n }\n }\n return rectToClientRect({\n width,\n height,\n x,\n y\n });\n}\n\n// If <html> has a CSS width greater than the viewport, then this will be\n// incorrect for RTL.\nfunction getWindowScrollBarX(element, rect) {\n const leftScroll = getNodeScroll(element).scrollLeft;\n if (!rect) {\n return getBoundingClientRect(getDocumentElement(element)).left + leftScroll;\n }\n return rect.left + leftScroll;\n}\n\nfunction getHTMLOffset(documentElement, scroll) {\n const htmlRect = documentElement.getBoundingClientRect();\n const x = htmlRect.left + scroll.scrollLeft - getWindowScrollBarX(documentElement, htmlRect);\n const y = htmlRect.top + scroll.scrollTop;\n return {\n x,\n y\n };\n}\n\nfunction convertOffsetParentRelativeRectToViewportRelativeRect(_ref) {\n let {\n elements,\n rect,\n offsetParent,\n strategy\n } = _ref;\n const isFixed = strategy === 'fixed';\n const documentElement = getDocumentElement(offsetParent);\n const topLayer = elements ? isTopLayer(elements.floating) : false;\n if (offsetParent === documentElement || topLayer && isFixed) {\n return rect;\n }\n let scroll = {\n scrollLeft: 0,\n scrollTop: 0\n };\n let scale = createCoords(1);\n const offsets = createCoords(0);\n const isOffsetParentAnElement = isHTMLElement(offsetParent);\n if (isOffsetParentAnElement || !isFixed) {\n if (getNodeName(offsetParent) !== 'body' || isOverflowElement(documentElement)) {\n scroll = getNodeScroll(offsetParent);\n }\n if (isOffsetParentAnElement) {\n const offsetRect = getBoundingClientRect(offsetParent);\n scale = getScale(offsetParent);\n offsets.x = offsetRect.x + offsetParent.clientLeft;\n offsets.y = offsetRect.y + offsetParent.clientTop;\n }\n }\n const htmlOffset = documentElement && !isOffsetParentAnElement && !isFixed ? getHTMLOffset(documentElement, scroll) : createCoords(0);\n return {\n width: rect.width * scale.x,\n height: rect.height * scale.y,\n x: rect.x * scale.x - scroll.scrollLeft * scale.x + offsets.x + htmlOffset.x,\n y: rect.y * scale.y - scroll.scrollTop * scale.y + offsets.y + htmlOffset.y\n };\n}\n\nfunction getClientRects(element) {\n return element.getClientRects ? Array.from(element.getClientRects()) : [];\n}\n\n// Gets the entire size of the scrollable document area, even extending outside\n// of the `<html>` and `<body>` rect bounds if horizontally scrollable.\nfunction getDocumentRect(html) {\n const scroll = getNodeScroll(html);\n const body = html.ownerDocument.body;\n const width = max(html.scrollWidth, html.clientWidth, body.scrollWidth, body.clientWidth);\n const height = max(html.scrollHeight, html.clientHeight, body.scrollHeight, body.clientHeight);\n let x = -scroll.scrollLeft + getWindowScrollBarX(html);\n const y = -scroll.scrollTop;\n if (getComputedStyle$1(body).direction === 'rtl') {\n x += max(html.clientWidth, body.clientWidth) - width;\n }\n return {\n width,\n height,\n x,\n y\n };\n}\n\n// Safety check: ensure the scrollbar space is reasonable in case this\n// calculation is affected by unusual styles.\n// Most scrollbars leave 15-18px of space.\nconst SCROLLBAR_MAX = 25;\nfunction getViewportRect(element, strategy, rootBoundary) {\n if (rootBoundary === void 0) {\n rootBoundary = 'viewport';\n }\n const isLayoutViewport = rootBoundary === 'layoutViewport';\n const win = getWindow(element);\n const html = getDocumentElement(element);\n const visualViewport = win.visualViewport;\n let width = html.clientWidth;\n let height = html.clientHeight;\n let x = 0;\n let y = 0;\n if (visualViewport) {\n // Client coordinates are relative to the layout viewport, except in\n // WebKit with an `absolute` strategy, where they are relative to the\n // visual viewport.\n const layoutRelativeClientCoords = !isWebKit() || strategy === 'fixed';\n if (isLayoutViewport) {\n if (!layoutRelativeClientCoords) {\n x = -visualViewport.offsetLeft;\n y = -visualViewport.offsetTop;\n }\n } else {\n width = visualViewport.width;\n height = visualViewport.height;\n if (layoutRelativeClientCoords) {\n x = visualViewport.offsetLeft;\n y = visualViewport.offsetTop;\n }\n }\n }\n const windowScrollbarX = getWindowScrollBarX(html);\n // `scrollbar-gutter: stable` on the <html> reserves gutter space that shrinks\n // the visual width but isn't reflected in `html.clientWidth`, so subtract it.\n // Only the inline-end (right) gutter can hold the scrollbar; `both-edges` also\n // reserves an empty inline-start gutter that clips nothing, so exclude just\n // the one scrollbar-side gutter — halve the measured (two-gutter) total. A\n // left-side scrollbar (`windowScrollbarX > 0`) is already handled by\n // `getHTMLOffset`/`visualViewport.width`; skip it here.\n if (windowScrollbarX <= 0) {\n const doc = html.ownerDocument;\n const body = doc.body;\n const bodyStyles = getComputedStyle(body);\n const bodyMarginInline = doc.compatMode === 'CSS1Compat' ? parseFloat(bodyStyles.marginLeft) + parseFloat(bodyStyles.marginRight) || 0 : 0;\n const reservedWidth = Math.abs(html.clientWidth - body.clientWidth - bodyMarginInline);\n const gutter = getComputedStyle(html).scrollbarGutter === 'stable both-edges' ? reservedWidth / 2 : reservedWidth;\n if (gutter <= SCROLLBAR_MAX) {\n width -= gutter;\n }\n }\n return {\n width,\n height,\n x,\n y\n };\n}\n\n// Returns the inner client rect, subtracting scrollbars if present.\nfunction getInnerBoundingClientRect(element, strategy) {\n const clientRect = getBoundingClientRect(element, true, strategy === 'fixed');\n const top = clientRect.top + element.clientTop;\n const left = clientRect.left + element.clientLeft;\n const scale = getScale(element);\n const width = element.clientWidth * scale.x;\n const height = element.clientHeight * scale.y;\n const x = left * scale.x;\n const y = top * scale.y;\n return {\n width,\n height,\n x,\n y\n };\n}\nfunction getClientRectFromClippingAncestor(element, clippingAncestor, strategy) {\n let rect;\n if (clippingAncestor === 'viewport' || clippingAncestor === 'layoutViewport') {\n rect = getViewportRect(element, strategy, clippingAncestor);\n } else if (clippingAncestor === 'document') {\n rect = getDocumentRect(getDocumentElement(element));\n } else if (isElement(clippingAncestor)) {\n rect = getInnerBoundingClientRect(clippingAncestor, strategy);\n } else {\n const visualOffsets = getVisualOffsets(element);\n rect = {\n x: clippingAncestor.x - visualOffsets.x,\n y: clippingAncestor.y - visualOffsets.y,\n width: clippingAncestor.width,\n height: clippingAncestor.height\n };\n }\n return rectToClientRect(rect);\n}\n\n// A \"clipping ancestor\" is an `overflow` element with the characteristic of\n// clipping (or hiding) child elements. This returns all clipping ancestors\n// of the given element up the tree.\nfunction getClippingElementAncestors(element, cache) {\n const cachedResult = cache.get(element);\n if (cachedResult) {\n return cachedResult;\n }\n let result = getOverflowAncestors(element, [], false).filter(el => isElement(el) && getNodeName(el) !== 'body');\n let lastKeptComputedStyle = null;\n const elementIsFixed = getComputedStyle$1(element).position === 'fixed';\n let currentNode = elementIsFixed ? getParentNode(element) : element;\n\n // https://developer.mozilla.org/en-US/docs/Web/CSS/Containing_block#identifying_the_containing_block\n while (isElement(currentNode) && !isLastTraversableNode(currentNode)) {\n const computedStyle = getComputedStyle$1(currentNode);\n const currentNodeIsContaining = isContainingBlock(currentNode);\n // Position of the containing block chain below the current node. A fixed\n // element whose containing block hasn't been found yet is a fixed chain.\n const lastPosition = lastKeptComputedStyle ? lastKeptComputedStyle.position : elementIsFixed ? 'fixed' : '';\n\n // A non-containing ancestor does not clip the element when the chain\n // below it escapes it: a fixed chain escapes all ancestors up to the\n // next containing block, an absolute chain escapes static ancestors.\n const shouldDropCurrentNode = !currentNodeIsContaining && (lastPosition === 'fixed' || lastPosition === 'absolute' && computedStyle.position === 'static');\n if (shouldDropCurrentNode) {\n // Drop non-containing blocks.\n result = result.filter(ancestor => ancestor !== currentNode);\n } else {\n // The kept node carries the chain position for the next iteration.\n lastKeptComputedStyle = computedStyle;\n }\n currentNode = getParentNode(currentNode);\n }\n cache.set(element, result);\n return result;\n}\n\n// Gets the maximum area that the element is visible in due to any number of\n// clipping ancestors.\nfunction getClippingRect(_ref) {\n let {\n element,\n boundary,\n rootBoundary,\n strategy\n } = _ref;\n const elementClippingAncestors = boundary === 'clippingAncestors' ? isTopLayer(element) ? [] : getClippingElementAncestors(element, this._c) : [].concat(boundary);\n const clippingAncestors = [...elementClippingAncestors, rootBoundary];\n const firstRect = getClientRectFromClippingAncestor(element, clippingAncestors[0], strategy);\n let top = firstRect.top;\n let right = firstRect.right;\n let bottom = firstRect.bottom;\n let left = firstRect.left;\n for (let i = 1; i < clippingAncestors.length; i++) {\n const rect = getClientRectFromClippingAncestor(element, clippingAncestors[i], strategy);\n top = max(rect.top, top);\n right = min(rect.right, right);\n bottom = min(rect.bottom, bottom);\n left = max(rect.left, left);\n }\n return {\n width: right - left,\n height: bottom - top,\n x: left,\n y: top\n };\n}\n\nfunction getDimensions(element) {\n const {\n width,\n height\n } = getCssDimensions(element);\n return {\n width,\n height\n };\n}\n\nfunction getRectRelativeToOffsetParent(element, offsetParent, strategy) {\n const isOffsetParentAnElement = isHTMLElement(offsetParent);\n const documentElement = getDocumentElement(offsetParent);\n const isFixed = strategy === 'fixed';\n const rect = getBoundingClientRect(element, true, isFixed, offsetParent);\n let scroll = {\n scrollLeft: 0,\n scrollTop: 0\n };\n const offsets = createCoords(0);\n if (isOffsetParentAnElement || !isFixed) {\n if (getNodeName(offsetParent) !== 'body' || isOverflowElement(documentElement)) {\n scroll = getNodeScroll(offsetParent);\n }\n if (isOffsetParentAnElement) {\n const offsetRect = getBoundingClientRect(offsetParent, true, isFixed, offsetParent);\n offsets.x = offsetRect.x + offsetParent.clientLeft;\n offsets.y = offsetRect.y + offsetParent.clientTop;\n }\n }\n\n // If the <body> scrollbar appears on the left (e.g. RTL systems). Use\n // Firefox with layout.scrollbar.side = 3 in about:config to test this.\n if (!isOffsetParentAnElement && documentElement) {\n offsets.x = getWindowScrollBarX(documentElement);\n }\n const htmlOffset = documentElement && !isOffsetParentAnElement && !isFixed ? getHTMLOffset(documentElement, scroll) : createCoords(0);\n const x = rect.left + scroll.scrollLeft - offsets.x - htmlOffset.x;\n const y = rect.top + scroll.scrollTop - offsets.y - htmlOffset.y;\n return {\n x,\n y,\n width: rect.width,\n height: rect.height\n };\n}\n\nfunction isStaticPositioned(element) {\n return getComputedStyle$1(element).position === 'static';\n}\n\nfunction getTrueOffsetParent(element, polyfill) {\n if (!isHTMLElement(element) || getComputedStyle$1(element).position === 'fixed') {\n return null;\n }\n if (polyfill) {\n return polyfill(element);\n }\n let rawOffsetParent = element.offsetParent;\n\n // Firefox returns the <html> element as the offsetParent if it's non-static,\n // while Chrome and Safari return the <body> element. The <body> element must\n // be used to perform the correct calculations even if the <html> element is\n // non-static.\n if (getDocumentElement(element) === rawOffsetParent) {\n rawOffsetParent = rawOffsetParent.ownerDocument.body;\n }\n return rawOffsetParent;\n}\n\n// Gets the closest ancestor positioned element. Handles some edge cases,\n// such as table ancestors and cross browser bugs.\nfunction getOffsetParent(element, polyfill) {\n const win = getWindow(element);\n if (isTopLayer(element)) {\n return win;\n }\n if (!isHTMLElement(element)) {\n let svgOffsetParent = getParentNode(element);\n while (svgOffsetParent && !isLastTraversableNode(svgOffsetParent)) {\n if (isElement(svgOffsetParent) && !isStaticPositioned(svgOffsetParent)) {\n return svgOffsetParent;\n }\n svgOffsetParent = getParentNode(svgOffsetParent);\n }\n return win;\n }\n let offsetParent = getTrueOffsetParent(element, polyfill);\n while (offsetParent && isTableElement(offsetParent) && isStaticPositioned(offsetParent)) {\n offsetParent = getTrueOffsetParent(offsetParent, polyfill);\n }\n if (offsetParent && isLastTraversableNode(offsetParent) && isStaticPositioned(offsetParent) && !isContainingBlock(offsetParent)) {\n return win;\n }\n return offsetParent || getContainingBlock(element) || win;\n}\n\nconst getElementRects = async function (data) {\n const getOffsetParentFn = this.getOffsetParent || getOffsetParent;\n const getDimensionsFn = this.getDimensions;\n const floatingDimensions = await getDimensionsFn(data.floating);\n return {\n reference: getRectRelativeToOffsetParent(data.reference, await getOffsetParentFn(data.floating), data.strategy),\n floating: {\n x: 0,\n y: 0,\n width: floatingDimensions.width,\n height: floatingDimensions.height\n }\n };\n};\n\nfunction isRTL(element) {\n return getComputedStyle$1(element).direction === 'rtl';\n}\n\nconst platform = {\n convertOffsetParentRelativeRectToViewportRelativeRect,\n getDocumentElement,\n getClippingRect,\n getOffsetParent,\n getElementRects,\n getClientRects,\n getDimensions,\n getScale,\n isElement,\n isRTL\n};\n\nfunction rectsAreEqual(a, b) {\n return a.x === b.x && a.y === b.y && a.width === b.width && a.height === b.height;\n}\n\n// https://samthor.au/2021/observing-dom/\nfunction observeMove(element, onMove, ancestorResize) {\n let io = null;\n let timeoutId;\n const root = getDocumentElement(element);\n function cleanup() {\n var _io;\n clearTimeout(timeoutId);\n (_io = io) == null || _io.disconnect();\n io = null;\n }\n function refresh(skip, threshold) {\n if (skip === void 0) {\n skip = false;\n }\n if (threshold === void 0) {\n threshold = 1;\n }\n cleanup();\n const elementRectForRootMargin = element.getBoundingClientRect();\n const {\n left,\n top,\n width,\n height\n } = elementRectForRootMargin;\n if (!skip) {\n onMove();\n }\n if (!width || !height) {\n return;\n }\n const insetTop = floor(top);\n const insetRight = floor(root.clientWidth - (left + width));\n const insetBottom = floor(root.clientHeight - (top + height));\n const insetLeft = floor(left);\n const rootMargin = -insetTop + \"px \" + -insetRight + \"px \" + -insetBottom + \"px \" + -insetLeft + \"px\";\n const options = {\n rootMargin,\n threshold: max(0, min(1, threshold)) || 1\n };\n let isFirstUpdate = true;\n function handleObserve(entries) {\n const ratio = entries[0].intersectionRatio;\n\n // The entry is a snapshot, so the reference may have moved since the\n // intersection was computed (under performance constraints, or between\n // consecutive frames of a multi-frame layout shift). The reported ratio\n // and the observed area are stale in that case and cannot be trusted to\n // detect subsequent movement, so refresh regardless of the ratio.\n if (!rectsAreEqual(elementRectForRootMargin, element.getBoundingClientRect())) {\n return refresh();\n }\n if (ratio !== threshold) {\n if (!isFirstUpdate) {\n return refresh();\n }\n if (!ratio) {\n // If the reference is clipped in place, the ratio is 0. Throttle\n // the refresh to prevent an infinite loop of updates.\n timeoutId = setTimeout(() => {\n refresh(false, 1e-7);\n }, 1000);\n } else {\n refresh(false, ratio);\n }\n }\n isFirstUpdate = false;\n }\n\n // Older browsers don't support a `document` as the root and will throw an\n // error.\n try {\n io = new IntersectionObserver(handleObserve, {\n ...options,\n // Handle <iframe>s\n root: root.ownerDocument\n });\n } catch (_e) {\n io = new IntersectionObserver(handleObserve, options);\n }\n io.observe(element);\n }\n const win = getWindow(element);\n // The window is a resize ancestor, so when `ancestorResize` is enabled its\n // listener already runs the update on resize. Here we only need to rebuild\n // the `IntersectionObserver` for the new root size, skipping a redundant\n // update. When `ancestorResize` is disabled, this becomes the sole update.\n const handleResize = () => refresh(ancestorResize);\n win.addEventListener('resize', handleResize);\n refresh(true);\n return () => {\n win.removeEventListener('resize', handleResize);\n cleanup();\n };\n}\n\n/**\n * Automatically updates the position of the floating element when necessary.\n * Should only be called when the floating element is mounted on the DOM or\n * visible on the screen.\n * @returns cleanup function that should be invoked when the floating element is\n * removed from the DOM or hidden from the screen.\n * @see https://floating-ui.com/docs/autoUpdate\n */\nfunction autoUpdate(reference, floating, update, options) {\n if (options === void 0) {\n options = {};\n }\n const {\n ancestorScroll = true,\n ancestorResize = true,\n elementResize = typeof ResizeObserver === 'function',\n layoutShift = typeof IntersectionObserver === 'function',\n animationFrame = false\n } = options;\n const referenceEl = unwrapElement(reference);\n const ancestors = ancestorScroll || ancestorResize ? [...(referenceEl ? getOverflowAncestors(referenceEl) : []), ...(floating ? getOverflowAncestors(floating) : [])] : [];\n ancestors.forEach(ancestor => {\n ancestorScroll && ancestor.addEventListener('scroll', update);\n ancestorResize && ancestor.addEventListener('resize', update);\n });\n const cleanupIo = referenceEl && layoutShift ? observeMove(referenceEl, update, ancestorResize) : null;\n let reobserveFrame = -1;\n let resizeObserver = null;\n if (elementResize) {\n resizeObserver = new ResizeObserver(_ref => {\n let [firstEntry] = _ref;\n if (firstEntry && firstEntry.target === referenceEl && resizeObserver && floating) {\n // Prevent update loops when using the `size` middleware.\n // https://github.com/floating-ui/floating-ui/issues/1740\n resizeObserver.unobserve(floating);\n cancelAnimationFrame(reobserveFrame);\n reobserveFrame = requestAnimationFrame(() => {\n var _resizeObserver;\n (_resizeObserver = resizeObserver) == null || _resizeObserver.observe(floating);\n });\n }\n update();\n });\n if (referenceEl && !animationFrame) {\n resizeObserver.observe(referenceEl);\n }\n if (floating) {\n resizeObserver.observe(floating);\n }\n }\n let frameId;\n let prevRefRect = animationFrame ? getBoundingClientRect(reference) : null;\n if (animationFrame) {\n frameLoop();\n }\n function frameLoop() {\n const nextRefRect = getBoundingClientRect(reference);\n if (prevRefRect && !rectsAreEqual(prevRefRect, nextRefRect)) {\n update();\n }\n prevRefRect = nextRefRect;\n frameId = requestAnimationFrame(frameLoop);\n }\n update();\n return () => {\n var _resizeObserver2;\n ancestors.forEach(ancestor => {\n ancestorScroll && ancestor.removeEventListener('scroll', update);\n ancestorResize && ancestor.removeEventListener('resize', update);\n });\n cleanupIo == null || cleanupIo();\n (_resizeObserver2 = resizeObserver) == null || _resizeObserver2.disconnect();\n resizeObserver = null;\n if (animationFrame) {\n cancelAnimationFrame(frameId);\n }\n };\n}\n\n/**\n * Resolves with an object of overflow side offsets that determine how much the\n * element is overflowing a given clipping boundary on each side.\n * - positive = overflowing the boundary by that number of pixels\n * - negative = how many pixels left before it will overflow\n * - 0 = lies flush with the boundary\n * @see https://floating-ui.com/docs/detectOverflow\n */\nconst detectOverflow = detectOverflow$1;\n\n/**\n * Modifies the placement by translating the floating element along the\n * specified axes.\n * A number (shorthand for `mainAxis` or distance), or an axes configuration\n * object may be passed.\n * @see https://floating-ui.com/docs/offset\n */\nconst offset = offset$1;\n\n/**\n * Optimizes the visibility of the floating element by choosing the placement\n * that has the most space available automatically, without needing to specify a\n * preferred placement. Alternative to `flip`.\n * @see https://floating-ui.com/docs/autoPlacement\n */\nconst autoPlacement = autoPlacement$1;\n\n/**\n * Optimizes the visibility of the floating element by shifting it in order to\n * keep it in view when it will overflow the clipping boundary.\n * @see https://floating-ui.com/docs/shift\n */\nconst shift = shift$1;\n\n/**\n * Optimizes the visibility of the floating element by flipping the `placement`\n * in order to keep it in view when the preferred placement(s) will overflow the\n * clipping boundary. Alternative to `autoPlacement`.\n * @see https://floating-ui.com/docs/flip\n */\nconst flip = flip$1;\n\n/**\n * Provides data that allows you to change the size of the floating element —\n * for instance, prevent it from overflowing the clipping boundary or match the\n * width of the reference element.\n * @see https://floating-ui.com/docs/size\n */\nconst size = size$1;\n\n/**\n * Provides data to hide the floating element in applicable situations, such as\n * when it is not in the same clipping context as the reference element.\n * @see https://floating-ui.com/docs/hide\n */\nconst hide = hide$1;\n\n/**\n * Provides data to position an inner element of the floating element so that it\n * appears centered to the reference element.\n * @see https://floating-ui.com/docs/arrow\n */\nconst arrow = arrow$1;\n\n/**\n * Provides improved positioning for inline reference elements that can span\n * over multiple lines, such as hyperlinks or range selections.\n * @see https://floating-ui.com/docs/inline\n */\nconst inline = inline$1;\n\n/**\n * Built-in `limiter` that will stop `shift()` at a certain point.\n */\nconst limitShift = limitShift$1;\n\n/**\n * Computes the `x` and `y` coordinates that will place the floating element\n * next to a given reference element.\n */\nconst computePosition = (reference, floating, options) => {\n // This caches the expensive `getClippingElementAncestors` function so that\n // multiple lifecycle resets re-use the same result. It only lives for a\n // single call. If other functions become expensive, we can add them as well.\n const cache = new Map();\n const mergedOptions = options != null ? options : {};\n const platformWithCache = {\n ...platform,\n ...mergedOptions.platform,\n _c: cache\n };\n return computePosition$1(reference, floating, {\n ...mergedOptions,\n platform: platformWithCache\n });\n};\n\nexport { arrow, autoPlacement, autoUpdate, computePosition, detectOverflow, flip, hide, inline, limitShift, offset, platform, shift, size };\n","import { computePosition, arrow as arrow$2, autoPlacement as autoPlacement$1, flip as flip$1, hide as hide$1, inline as inline$1, limitShift as limitShift$1, offset as offset$1, shift as shift$1, size as size$1 } from '@floating-ui/dom';\nexport { autoUpdate, computePosition, detectOverflow, getOverflowAncestors, platform } from '@floating-ui/dom';\nimport * as React from 'react';\nimport { useLayoutEffect } from 'react';\nimport * as ReactDOM from 'react-dom';\n\nvar isClient = typeof document !== 'undefined';\n\nvar noop = function noop() {};\nvar index = isClient ? useLayoutEffect : noop;\n\n// Fork of `fast-deep-equal` that only does the comparisons we need and compares\n// functions\nfunction deepEqual(a, b) {\n if (a === b) {\n return true;\n }\n if (typeof a !== typeof b) {\n return false;\n }\n if (typeof a === 'function' && a.toString() === b.toString()) {\n return true;\n }\n let length;\n let i;\n let keys;\n if (a && b && typeof a === 'object') {\n if (Array.isArray(a)) {\n length = a.length;\n if (length !== b.length) return false;\n for (i = length; i-- !== 0;) {\n if (!deepEqual(a[i], b[i])) {\n return false;\n }\n }\n return true;\n }\n keys = Object.keys(a);\n length = keys.length;\n if (length !== Object.keys(b).length) {\n return false;\n }\n for (i = length; i-- !== 0;) {\n if (!{}.hasOwnProperty.call(b, keys[i])) {\n return false;\n }\n }\n for (i = length; i-- !== 0;) {\n const key = keys[i];\n if (key === '_owner' && a.$$typeof) {\n continue;\n }\n if (!deepEqual(a[key], b[key])) {\n return false;\n }\n }\n return true;\n }\n return a !== a && b !== b;\n}\n\nfunction getDPR(element) {\n if (typeof window === 'undefined') {\n return 1;\n }\n const win = element.ownerDocument.defaultView || window;\n return win.devicePixelRatio || 1;\n}\n\nfunction roundByDPR(element, value) {\n const dpr = getDPR(element);\n return Math.round(value * dpr) / dpr;\n}\n\nfunction useLatestRef(value) {\n const ref = React.useRef(value);\n index(() => {\n ref.current = value;\n });\n return ref;\n}\n\n/**\n * Provides data to position a floating element.\n * @see https://floating-ui.com/docs/useFloating\n */\nfunction useFloating(options) {\n if (options === void 0) {\n options = {};\n }\n const {\n placement = 'bottom',\n strategy = 'absolute',\n middleware = [],\n platform,\n elements: {\n reference: externalReference,\n floating: externalFloating\n } = {},\n transform = true,\n whileElementsMounted,\n open\n } = options;\n const [data, setData] = React.useState({\n x: 0,\n y: 0,\n strategy,\n placement,\n middlewareData: {},\n isPositioned: false\n });\n const [latestMiddleware, setLatestMiddleware] = React.useState(middleware);\n if (!deepEqual(latestMiddleware, middleware)) {\n setLatestMiddleware(middleware);\n }\n const [_reference, _setReference] = React.useState(null);\n const [_floating, _setFloating] = React.useState(null);\n const setReference = React.useCallback(node => {\n if (node !== referenceRef.current) {\n referenceRef.current = node;\n _setReference(node);\n }\n }, []);\n const setFloating = React.useCallback(node => {\n if (node !== floatingRef.current) {\n floatingRef.current = node;\n _setFloating(node);\n }\n }, []);\n const referenceEl = externalReference || _reference;\n const floatingEl = externalFloating || _floating;\n const referenceRef = React.useRef(null);\n const floatingRef = React.useRef(null);\n const dataRef = React.useRef(data);\n const hasWhileElementsMounted = whileElementsMounted != null;\n const whileElementsMountedRef = useLatestRef(whileElementsMounted);\n const platformRef = useLatestRef(platform);\n const openRef = useLatestRef(open);\n const update = React.useCallback(() => {\n if (!referenceRef.current || !floatingRef.current) {\n return;\n }\n const config = {\n placement,\n strategy,\n middleware: latestMiddleware\n };\n if (platformRef.current) {\n config.platform = platformRef.current;\n }\n computePosition(referenceRef.current, floatingRef.current, config).then(data => {\n const fullData = {\n ...data,\n // The floating element's position may be recomputed while it's closed\n // but still mounted (such as when transitioning out). To ensure\n // `isPositioned` will be `false` initially on the next open, avoid\n // setting it to `true` when `open === false` (must be specified).\n isPositioned: openRef.current !== false\n };\n if (isMountedRef.current && !deepEqual(dataRef.current, fullData)) {\n dataRef.current = fullData;\n ReactDOM.flushSync(() => {\n setData(fullData);\n });\n }\n });\n }, [latestMiddleware, placement, strategy, platformRef, openRef]);\n index(() => {\n if (open === false && dataRef.current.isPositioned) {\n dataRef.current.isPositioned = false;\n setData(data => ({\n ...data,\n isPositioned: false\n }));\n }\n }, [open]);\n const isMountedRef = React.useRef(false);\n index(() => {\n isMountedRef.current = true;\n return () => {\n isMountedRef.current = false;\n };\n }, []);\n index(() => {\n if (referenceEl) referenceRef.current = referenceEl;\n if (floatingEl) floatingRef.current = floatingEl;\n if (referenceEl && floatingEl) {\n if (whileElementsMountedRef.current) {\n return whileElementsMountedRef.current(referenceEl, floatingEl, update);\n }\n update();\n }\n }, [referenceEl, floatingEl, update, whileElementsMountedRef, hasWhileElementsMounted]);\n const refs = React.useMemo(() => ({\n reference: referenceRef,\n floating: floatingRef,\n setReference,\n setFloating\n }), [setReference, setFloating]);\n const elements = React.useMemo(() => ({\n reference: referenceEl,\n floating: floatingEl\n }), [referenceEl, floatingEl]);\n const floatingStyles = React.useMemo(() => {\n const initialStyles = {\n position: strategy,\n left: 0,\n top: 0\n };\n if (!elements.floating) {\n return initialStyles;\n }\n const x = roundByDPR(elements.floating, data.x);\n const y = roundByDPR(elements.floating, data.y);\n if (transform) {\n return {\n ...initialStyles,\n transform: \"translate(\" + x + \"px, \" + y + \"px)\",\n ...(getDPR(elements.floating) >= 1.5 && {\n willChange: 'transform'\n })\n };\n }\n return {\n position: strategy,\n left: x,\n top: y\n };\n }, [strategy, transform, elements.floating, data.x, data.y]);\n return React.useMemo(() => ({\n ...data,\n update,\n refs,\n elements,\n floatingStyles\n }), [data, update, refs, elements, floatingStyles]);\n}\n\n/**\n * Provides data to position an inner element of the floating element so that it\n * appears centered to the reference element.\n * This wraps the core `arrow` middleware to allow React refs as the element.\n * @see https://floating-ui.com/docs/arrow\n */\nconst arrow$1 = options => {\n function isRef(value) {\n return {}.hasOwnProperty.call(value, 'current');\n }\n return {\n name: 'arrow',\n options,\n fn(state) {\n const {\n element,\n padding\n } = typeof options === 'function' ? options(state) : options;\n if (element && isRef(element)) {\n if (element.current != null) {\n return arrow$2({\n element: element.current,\n padding\n }).fn(state);\n }\n return {};\n }\n if (element) {\n return arrow$2({\n element,\n padding\n }).fn(state);\n }\n return {};\n }\n };\n};\n\n/**\n * Modifies the placement by translating the floating element along the\n * specified axes.\n * A number (shorthand for `mainAxis` or distance), or an axes configuration\n * object may be passed.\n * @see https://floating-ui.com/docs/offset\n */\nconst offset = (options, deps) => {\n const result = offset$1(options);\n return {\n name: result.name,\n fn: result.fn,\n options: [options, deps]\n };\n};\n\n/**\n * Optimizes the visibility of the floating element by shifting it in order to\n * keep it in view when it will overflow the clipping boundary.\n * @see https://floating-ui.com/docs/shift\n */\nconst shift = (options, deps) => {\n const result = shift$1(options);\n return {\n name: result.name,\n fn: result.fn,\n options: [options, deps]\n };\n};\n\n/**\n * Built-in `limiter` that will stop `shift()` at a certain point.\n */\nconst limitShift = (options, deps) => {\n const result = limitShift$1(options);\n return {\n fn: result.fn,\n options: [options, deps]\n };\n};\n\n/**\n * Optimizes the visibility of the floating element by flipping the `placement`\n * in order to keep it in view when the preferred placement(s) will overflow the\n * clipping boundary. Alternative to `autoPlacement`.\n * @see https://floating-ui.com/docs/flip\n */\nconst flip = (options, deps) => {\n const result = flip$1(options);\n return {\n name: result.name,\n fn: result.fn,\n options: [options, deps]\n };\n};\n\n/**\n * Provides data that allows you to change the size of the floating element —\n * for instance, prevent it from overflowing the clipping boundary or match the\n * width of the reference element.\n * @see https://floating-ui.com/docs/size\n */\nconst size = (options, deps) => {\n const result = size$1(options);\n return {\n name: result.name,\n fn: result.fn,\n options: [options, deps]\n };\n};\n\n/**\n * Optimizes the visibility of the floating element by choosing the placement\n * that has the most space available automatically, without needing to specify a\n * preferred placement. Alternative to `flip`.\n * @see https://floating-ui.com/docs/autoPlacement\n */\nconst autoPlacement = (options, deps) => {\n const result = autoPlacement$1(options);\n return {\n name: result.name,\n fn: result.fn,\n options: [options, deps]\n };\n};\n\n/**\n * Provides data to hide the floating element in applicable situations, such as\n * when it is not in the same clipping context as the reference element.\n * @see https://floating-ui.com/docs/hide\n */\nconst hide = (options, deps) => {\n const result = hide$1(options);\n return {\n name: result.name,\n fn: result.fn,\n options: [options, deps]\n };\n};\n\n/**\n * Provides improved positioning for inline reference elements that can span\n * over multiple lines, such as hyperlinks or range selections.\n * @see https://floating-ui.com/docs/inline\n */\nconst inline = (options, deps) => {\n const result = inline$1(options);\n return {\n name: result.name,\n fn: result.fn,\n options: [options, deps]\n };\n};\n\n/**\n * Provides data to position an inner element of the floating element so that it\n * appears centered to the reference element.\n * This wraps the core `arrow` middleware to allow React refs as the element.\n * @see https://floating-ui.com/docs/arrow\n */\nconst arrow = (options, deps) => {\n const result = arrow$1(options);\n return {\n name: result.name,\n fn: result.fn,\n options: [options, deps]\n };\n};\n\nexport { arrow, autoPlacement, flip, hide, inline, limitShift, offset, shift, size, useFloating };\n","import * as React from 'react';\nimport { useModernLayoutEffect, useEffectEvent, getMinListIndex, getMaxListIndex, createGridCellMap, isListIndexDisabled, getGridNavigatedIndex, getGridCellIndexOfCorner, getGridCellIndices, findNonDisabledListIndex, isIndexOutOfListBounds, useLatestRef, getDocument as getDocument$1, isMouseLikePointerType, contains as contains$1, isSafari, enableFocusInside, isOutsideEvent, getPreviousTabbable, getNextTabbable, disableFocusInside, isTypeableCombobox, getFloatingFocusElement, getTabbableOptions, getNodeAncestors, activeElement, getNodeChildren as getNodeChildren$1, stopEvent, getTarget as getTarget$1, isVirtualClick, isVirtualPointerEvent, getPlatform, isTypeableElement, isReactEvent, isRootElement, isEventTargetWithin, matchesFocusVisible, isMac, getDeepestNode, getUserAgent } from '@floating-ui/react/utils';\nimport { jsx, jsxs, Fragment } from 'react/jsx-runtime';\nimport { getComputedStyle, isElement, isShadowRoot, getNodeName, isNode, isHTMLElement, getWindow, isLastTraversableNode, getParentNode, isWebKit } from '@floating-ui/utils/dom';\nimport { tabbable, isTabbable, focusable } from 'tabbable';\nimport * as ReactDOM from 'react-dom';\nimport { getOverflowAncestors, useFloating as useFloating$1, offset } from '@floating-ui/react-dom';\nexport { arrow, autoPlacement, autoUpdate, computePosition, detectOverflow, flip, getOverflowAncestors, hide, inline, limitShift, offset, platform, shift, size } from '@floating-ui/react-dom';\nimport { evaluate, max, min, round } from '@floating-ui/utils';\n\n/**\n * Merges an array of refs into a single memoized callback ref or `null`.\n * @see https://floating-ui.com/docs/react-utils#usemergerefs\n */\nfunction useMergeRefs(refs) {\n const cleanupRef = React.useRef(undefined);\n const refEffect = React.useCallback(instance => {\n const cleanups = refs.map(ref => {\n if (ref == null) {\n return;\n }\n if (typeof ref === 'function') {\n const refCallback = ref;\n const refCleanup = refCallback(instance);\n return typeof refCleanup === 'function' ? refCleanup : () => {\n refCallback(null);\n };\n }\n ref.current = instance;\n return () => {\n ref.current = null;\n };\n });\n return () => {\n cleanups.forEach(refCleanup => refCleanup == null ? void 0 : refCleanup());\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, refs);\n return React.useMemo(() => {\n if (refs.every(ref => ref == null)) {\n return null;\n }\n return value => {\n if (cleanupRef.current) {\n cleanupRef.current();\n cleanupRef.current = undefined;\n }\n if (value != null) {\n cleanupRef.current = refEffect(value);\n }\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, refs);\n}\n\nfunction sortByDocumentPosition(a, b) {\n const position = a.compareDocumentPosition(b);\n if (position & Node.DOCUMENT_POSITION_FOLLOWING || position & Node.DOCUMENT_POSITION_CONTAINED_BY) {\n return -1;\n }\n if (position & Node.DOCUMENT_POSITION_PRECEDING || position & Node.DOCUMENT_POSITION_CONTAINS) {\n return 1;\n }\n return 0;\n}\nconst FloatingListContext = /*#__PURE__*/React.createContext({\n register: () => {},\n unregister: () => {},\n map: /*#__PURE__*/new Map(),\n elementsRef: {\n current: []\n }\n});\n/**\n * Provides context for a list of items within the floating element.\n * @see https://floating-ui.com/docs/FloatingList\n */\nfunction FloatingList(props) {\n const {\n children,\n elementsRef,\n labelsRef\n } = props;\n const [nodes, setNodes] = React.useState(() => new Set());\n const register = React.useCallback(node => {\n setNodes(prevSet => new Set(prevSet).add(node));\n }, []);\n const unregister = React.useCallback(node => {\n setNodes(prevSet => {\n const set = new Set(prevSet);\n set.delete(node);\n return set;\n });\n }, []);\n const map = React.useMemo(() => {\n const newMap = new Map();\n const sortedNodes = Array.from(nodes.keys()).sort(sortByDocumentPosition);\n sortedNodes.forEach((node, index) => {\n newMap.set(node, index);\n });\n return newMap;\n }, [nodes]);\n return /*#__PURE__*/jsx(FloatingListContext.Provider, {\n value: React.useMemo(() => ({\n register,\n unregister,\n map,\n elementsRef,\n labelsRef\n }), [register, unregister, map, elementsRef, labelsRef]),\n children: children\n });\n}\n/**\n * Used to register a list item and its index (DOM position) in the\n * `FloatingList`.\n * @see https://floating-ui.com/docs/FloatingList#uselistitem\n */\nfunction useListItem(props) {\n if (props === void 0) {\n props = {};\n }\n const {\n label\n } = props;\n const {\n register,\n unregister,\n map,\n elementsRef,\n labelsRef\n } = React.useContext(FloatingListContext);\n const [index, setIndex] = React.useState(null);\n const componentRef = React.useRef(null);\n const ref = React.useCallback(node => {\n componentRef.current = node;\n if (index !== null) {\n elementsRef.current[index] = node;\n if (labelsRef) {\n var _node$textContent;\n const isLabelDefined = label !== undefined;\n labelsRef.current[index] = isLabelDefined ? label : (_node$textContent = node == null ? void 0 : node.textContent) != null ? _node$textContent : null;\n }\n }\n }, [index, elementsRef, labelsRef, label]);\n useModernLayoutEffect(() => {\n const node = componentRef.current;\n if (node) {\n register(node);\n return () => {\n unregister(node);\n };\n }\n }, [register, unregister]);\n useModernLayoutEffect(() => {\n const index = componentRef.current ? map.get(componentRef.current) : null;\n if (index != null) {\n setIndex(index);\n }\n }, [map]);\n return React.useMemo(() => ({\n ref,\n index: index == null ? -1 : index\n }), [index, ref]);\n}\n\nconst FOCUSABLE_ATTRIBUTE = 'data-floating-ui-focusable';\nconst ACTIVE_KEY = 'active';\nconst SELECTED_KEY = 'selected';\nconst ARROW_LEFT = 'ArrowLeft';\nconst ARROW_RIGHT = 'ArrowRight';\nconst ARROW_UP = 'ArrowUp';\nconst ARROW_DOWN = 'ArrowDown';\n\nfunction renderJsx(render, computedProps) {\n if (typeof render === 'function') {\n return render(computedProps);\n }\n if (render) {\n return /*#__PURE__*/React.cloneElement(render, computedProps);\n }\n return /*#__PURE__*/jsx(\"div\", {\n ...computedProps\n });\n}\nconst CompositeContext = /*#__PURE__*/React.createContext({\n activeIndex: 0,\n onNavigate: () => {}\n});\nconst horizontalKeys = [ARROW_LEFT, ARROW_RIGHT];\nconst verticalKeys = [ARROW_UP, ARROW_DOWN];\nconst allKeys = [...horizontalKeys, ...verticalKeys];\n\n/**\n * Creates a single tab stop whose items are navigated by arrow keys, which\n * provides list navigation outside of floating element contexts.\n *\n * This is useful to enable navigation of a list of items that aren’t part of a\n * floating element. A menubar is an example of a composite, with each reference\n * element being an item.\n * @see https://floating-ui.com/docs/Composite\n */\nconst Composite = /*#__PURE__*/React.forwardRef(function Composite(props, forwardedRef) {\n const {\n render,\n orientation = 'both',\n loop = true,\n rtl = false,\n cols = 1,\n disabledIndices,\n activeIndex: externalActiveIndex,\n onNavigate: externalSetActiveIndex,\n itemSizes,\n dense = false,\n ...domProps\n } = props;\n const [internalActiveIndex, internalSetActiveIndex] = React.useState(0);\n const activeIndex = externalActiveIndex != null ? externalActiveIndex : internalActiveIndex;\n const onNavigate = useEffectEvent(externalSetActiveIndex != null ? externalSetActiveIndex : internalSetActiveIndex);\n const elementsRef = React.useRef([]);\n const renderElementProps = render && typeof render !== 'function' ? render.props : {};\n const contextValue = React.useMemo(() => ({\n activeIndex,\n onNavigate\n }), [activeIndex, onNavigate]);\n const isGrid = cols > 1;\n function handleKeyDown(event) {\n if (!allKeys.includes(event.key)) return;\n let nextIndex = activeIndex;\n const minIndex = getMinListIndex(elementsRef, disabledIndices);\n const maxIndex = getMaxListIndex(elementsRef, disabledIndices);\n const horizontalEndKey = rtl ? ARROW_LEFT : ARROW_RIGHT;\n const horizontalStartKey = rtl ? ARROW_RIGHT : ARROW_LEFT;\n if (isGrid) {\n const sizes = itemSizes || Array.from({\n length: elementsRef.current.length\n }, () => ({\n width: 1,\n height: 1\n }));\n // To calculate movements on the grid, we use hypothetical cell indices\n // as if every item was 1x1, then convert back to real indices.\n const cellMap = createGridCellMap(sizes, cols, dense);\n const minGridIndex = cellMap.findIndex(index => index != null && !isListIndexDisabled(elementsRef, index, disabledIndices));\n // last enabled index\n const maxGridIndex = cellMap.reduce((foundIndex, index, cellIndex) => index != null && !isListIndexDisabled(elementsRef, index, disabledIndices) ? cellIndex : foundIndex, -1);\n const maybeNextIndex = cellMap[getGridNavigatedIndex({\n current: cellMap.map(itemIndex => itemIndex ? elementsRef.current[itemIndex] : null)\n }, {\n event,\n orientation,\n loop,\n rtl,\n cols,\n // treat undefined (empty grid spaces) as disabled indices so we\n // don't end up in them\n disabledIndices: getGridCellIndices([...((typeof disabledIndices !== 'function' ? disabledIndices : null) || elementsRef.current.map((_, index) => isListIndexDisabled(elementsRef, index, disabledIndices) ? index : undefined)), undefined], cellMap),\n minIndex: minGridIndex,\n maxIndex: maxGridIndex,\n prevIndex: getGridCellIndexOfCorner(activeIndex > maxIndex ? minIndex : activeIndex, sizes, cellMap, cols,\n // use a corner matching the edge closest to the direction we're\n // moving in so we don't end up in the same item. Prefer\n // top/left over bottom/right.\n event.key === ARROW_DOWN ? 'bl' : event.key === horizontalEndKey ? 'tr' : 'tl')\n })];\n if (maybeNextIndex != null) {\n nextIndex = maybeNextIndex;\n }\n }\n const toEndKeys = {\n horizontal: [horizontalEndKey],\n vertical: [ARROW_DOWN],\n both: [horizontalEndKey, ARROW_DOWN]\n }[orientation];\n const toStartKeys = {\n horizontal: [horizontalStartKey],\n vertical: [ARROW_UP],\n both: [horizontalStartKey, ARROW_UP]\n }[orientation];\n const preventedKeys = isGrid ? allKeys : {\n horizontal: horizontalKeys,\n vertical: verticalKeys,\n both: allKeys\n }[orientation];\n if (nextIndex === activeIndex && [...toEndKeys, ...toStartKeys].includes(event.key)) {\n if (loop && nextIndex === maxIndex && toEndKeys.includes(event.key)) {\n nextIndex = minIndex;\n } else if (loop && nextIndex === minIndex && toStartKeys.includes(event.key)) {\n nextIndex = maxIndex;\n } else {\n nextIndex = findNonDisabledListIndex(elementsRef, {\n startingIndex: nextIndex,\n decrement: toStartKeys.includes(event.key),\n disabledIndices\n });\n }\n }\n if (nextIndex !== activeIndex && !isIndexOutOfListBounds(elementsRef, nextIndex)) {\n var _elementsRef$current$;\n event.stopPropagation();\n if (preventedKeys.includes(event.key)) {\n event.preventDefault();\n }\n onNavigate(nextIndex);\n (_elementsRef$current$ = elementsRef.current[nextIndex]) == null || _elementsRef$current$.focus();\n }\n }\n const computedProps = {\n ...domProps,\n ...renderElementProps,\n ref: forwardedRef,\n 'aria-orientation': orientation === 'both' ? undefined : orientation,\n onKeyDown(e) {\n domProps.onKeyDown == null || domProps.onKeyDown(e);\n renderElementProps.onKeyDown == null || renderElementProps.onKeyDown(e);\n handleKeyDown(e);\n }\n };\n return /*#__PURE__*/jsx(CompositeContext.Provider, {\n value: contextValue,\n children: /*#__PURE__*/jsx(FloatingList, {\n elementsRef: elementsRef,\n children: renderJsx(render, computedProps)\n })\n });\n});\n/**\n * @see https://floating-ui.com/docs/Composite\n */\nconst CompositeItem = /*#__PURE__*/React.forwardRef(function CompositeItem(props, forwardedRef) {\n const {\n render,\n ...domProps\n } = props;\n const renderElementProps = render && typeof render !== 'function' ? render.props : {};\n const {\n activeIndex,\n onNavigate\n } = React.useContext(CompositeContext);\n const {\n ref,\n index\n } = useListItem();\n const mergedRef = useMergeRefs([ref, forwardedRef, renderElementProps.ref]);\n const isActive = activeIndex === index;\n const computedProps = {\n ...domProps,\n ...renderElementProps,\n ref: mergedRef,\n tabIndex: isActive ? 0 : -1,\n 'data-active': isActive ? '' : undefined,\n onFocus(e) {\n domProps.onFocus == null || domProps.onFocus(e);\n renderElementProps.onFocus == null || renderElementProps.onFocus(e);\n onNavigate(index);\n }\n };\n return renderJsx(render, computedProps);\n});\n\n// https://github.com/mui/material-ui/issues/41190#issuecomment-2040873379\nconst SafeReact = {\n ...React\n};\n\nlet serverHandoffComplete = false;\nlet count = 0;\nconst genId = () => // Ensure the id is unique with multiple independent versions of Floating UI\n// on <React 18\n\"floating-ui-\" + Math.random().toString(36).slice(2, 6) + count++;\nfunction useFloatingId() {\n const [id, setId] = React.useState(() => serverHandoffComplete ? genId() : undefined);\n useModernLayoutEffect(() => {\n if (id == null) {\n setId(genId());\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n React.useEffect(() => {\n serverHandoffComplete = true;\n }, []);\n return id;\n}\nconst useReactId = SafeReact.useId;\n\n/**\n * Uses React 18's built-in `useId()` when available, or falls back to a\n * slightly less performant (requiring a double render) implementation for\n * earlier React versions.\n * @see https://floating-ui.com/docs/react-utils#useid\n */\nconst useId = useReactId || useFloatingId;\n\nlet devMessageSet;\nif (process.env.NODE_ENV !== \"production\") {\n devMessageSet = /*#__PURE__*/new Set();\n}\nfunction warn() {\n var _devMessageSet;\n for (var _len = arguments.length, messages = new Array(_len), _key = 0; _key < _len; _key++) {\n messages[_key] = arguments[_key];\n }\n const message = \"Floating UI: \" + messages.join(' ');\n if (!((_devMessageSet = devMessageSet) != null && _devMessageSet.has(message))) {\n var _devMessageSet2;\n (_devMessageSet2 = devMessageSet) == null || _devMessageSet2.add(message);\n console.warn(message);\n }\n}\nfunction error() {\n var _devMessageSet3;\n for (var _len2 = arguments.length, messages = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {\n messages[_key2] = arguments[_key2];\n }\n const message = \"Floating UI: \" + messages.join(' ');\n if (!((_devMessageSet3 = devMessageSet) != null && _devMessageSet3.has(message))) {\n var _devMessageSet4;\n (_devMessageSet4 = devMessageSet) == null || _devMessageSet4.add(message);\n console.error(message);\n }\n}\n\n/**\n * Renders a pointing arrow triangle.\n * @see https://floating-ui.com/docs/FloatingArrow\n */\nconst FloatingArrow = /*#__PURE__*/React.forwardRef(function FloatingArrow(props, ref) {\n const {\n context: {\n placement,\n elements: {\n floating\n },\n middlewareData: {\n arrow,\n shift\n }\n },\n width = 14,\n height = 7,\n tipRadius = 0,\n strokeWidth = 0,\n staticOffset,\n stroke,\n d,\n style: {\n transform,\n ...restStyle\n } = {},\n ...rest\n } = props;\n if (process.env.NODE_ENV !== \"production\") {\n if (!ref) {\n warn('The `ref` prop is required for `FloatingArrow`.');\n }\n }\n const clipPathId = useId();\n const [isRTL, setIsRTL] = React.useState(false);\n\n // https://github.com/floating-ui/floating-ui/issues/2932\n useModernLayoutEffect(() => {\n if (!floating) return;\n const isRTL = getComputedStyle(floating).direction === 'rtl';\n if (isRTL) {\n setIsRTL(true);\n }\n }, [floating]);\n if (!floating) {\n return null;\n }\n const [side, alignment] = placement.split('-');\n const isVerticalSide = side === 'top' || side === 'bottom';\n let computedStaticOffset = staticOffset;\n if (isVerticalSide && shift != null && shift.x || !isVerticalSide && shift != null && shift.y) {\n computedStaticOffset = null;\n }\n\n // Strokes must be double the border width, this ensures the stroke's width\n // works as you'd expect.\n const computedStrokeWidth = strokeWidth * 2;\n const halfStrokeWidth = computedStrokeWidth / 2;\n const svgX = width / 2 * (tipRadius / -8 + 1);\n const svgY = height / 2 * tipRadius / 4;\n const isCustomShape = !!d;\n const yOffsetProp = computedStaticOffset && alignment === 'end' ? 'bottom' : 'top';\n let xOffsetProp = computedStaticOffset && alignment === 'end' ? 'right' : 'left';\n if (computedStaticOffset && isRTL) {\n xOffsetProp = alignment === 'end' ? 'left' : 'right';\n }\n const arrowX = (arrow == null ? void 0 : arrow.x) != null ? computedStaticOffset || arrow.x : '';\n const arrowY = (arrow == null ? void 0 : arrow.y) != null ? computedStaticOffset || arrow.y : '';\n const dValue = d || 'M0,0' + (\" H\" + width) + (\" L\" + (width - svgX) + \",\" + (height - svgY)) + (\" Q\" + width / 2 + \",\" + height + \" \" + svgX + \",\" + (height - svgY)) + ' Z';\n const rotation = {\n top: isCustomShape ? 'rotate(180deg)' : '',\n left: isCustomShape ? 'rotate(90deg)' : 'rotate(-90deg)',\n bottom: isCustomShape ? '' : 'rotate(180deg)',\n right: isCustomShape ? 'rotate(-90deg)' : 'rotate(90deg)'\n }[side];\n return /*#__PURE__*/jsxs(\"svg\", {\n ...rest,\n \"aria-hidden\": true,\n ref: ref,\n width: isCustomShape ? width : width + computedStrokeWidth,\n height: width,\n viewBox: \"0 0 \" + width + \" \" + (height > width ? height : width),\n style: {\n position: 'absolute',\n pointerEvents: 'none',\n [xOffsetProp]: arrowX,\n [yOffsetProp]: arrowY,\n [side]: isVerticalSide || isCustomShape ? '100%' : \"calc(100% - \" + computedStrokeWidth / 2 + \"px)\",\n transform: [rotation, transform].filter(t => !!t).join(' '),\n ...restStyle\n },\n children: [computedStrokeWidth > 0 && /*#__PURE__*/jsx(\"path\", {\n clipPath: \"url(#\" + clipPathId + \")\",\n fill: \"none\",\n stroke: stroke\n // Account for the stroke on the fill path rendered below.\n ,\n strokeWidth: computedStrokeWidth + (d ? 0 : 1),\n d: dValue\n }), /*#__PURE__*/jsx(\"path\", {\n stroke: computedStrokeWidth && !d ? rest.fill : 'none',\n d: dValue\n }), /*#__PURE__*/jsx(\"clipPath\", {\n id: clipPathId,\n children: /*#__PURE__*/jsx(\"rect\", {\n x: -halfStrokeWidth,\n y: halfStrokeWidth * (isCustomShape ? -1 : 1),\n width: width + computedStrokeWidth,\n height: width\n })\n })]\n });\n});\n\nfunction createEventEmitter() {\n const map = new Map();\n return {\n emit(event, data) {\n var _map$get;\n (_map$get = map.get(event)) == null || _map$get.forEach(listener => listener(data));\n },\n on(event, listener) {\n if (!map.has(event)) {\n map.set(event, new Set());\n }\n map.get(event).add(listener);\n },\n off(event, listener) {\n var _map$get2;\n (_map$get2 = map.get(event)) == null || _map$get2.delete(listener);\n }\n };\n}\n\nconst FloatingNodeContext = /*#__PURE__*/React.createContext(null);\nconst FloatingTreeContext = /*#__PURE__*/React.createContext(null);\n\n/**\n * Returns the parent node id for nested floating elements, if available.\n * Returns `null` for top-level floating elements.\n */\nconst useFloatingParentNodeId = () => {\n var _React$useContext;\n return ((_React$useContext = React.useContext(FloatingNodeContext)) == null ? void 0 : _React$useContext.id) || null;\n};\n\n/**\n * Returns the nearest floating tree context, if available.\n */\nconst useFloatingTree = () => React.useContext(FloatingTreeContext);\n\n/**\n * Registers a node into the `FloatingTree`, returning its id.\n * @see https://floating-ui.com/docs/FloatingTree\n */\nfunction useFloatingNodeId(customParentId) {\n const id = useId();\n const tree = useFloatingTree();\n const reactParentId = useFloatingParentNodeId();\n const parentId = customParentId || reactParentId;\n useModernLayoutEffect(() => {\n if (!id) return;\n const node = {\n id,\n parentId\n };\n tree == null || tree.addNode(node);\n return () => {\n tree == null || tree.removeNode(node);\n };\n }, [tree, id, parentId]);\n return id;\n}\n/**\n * Provides parent node context for nested floating elements.\n * @see https://floating-ui.com/docs/FloatingTree\n */\nfunction FloatingNode(props) {\n const {\n children,\n id\n } = props;\n const parentId = useFloatingParentNodeId();\n return /*#__PURE__*/jsx(FloatingNodeContext.Provider, {\n value: React.useMemo(() => ({\n id,\n parentId\n }), [id, parentId]),\n children: children\n });\n}\n/**\n * Provides context for nested floating elements when they are not children of\n * each other on the DOM.\n * This is not necessary in all cases, except when there must be explicit communication between parent and child floating elements. It is necessary for:\n * - The `bubbles` option in the `useDismiss()` Hook\n * - Nested virtual list navigation\n * - Nested floating elements that each open on hover\n * - Custom communication between parent and child floating elements\n * @see https://floating-ui.com/docs/FloatingTree\n */\nfunction FloatingTree(props) {\n const {\n children\n } = props;\n const nodesRef = React.useRef([]);\n const addNode = React.useCallback(node => {\n nodesRef.current = [...nodesRef.current, node];\n }, []);\n const removeNode = React.useCallback(node => {\n nodesRef.current = nodesRef.current.filter(n => n !== node);\n }, []);\n const [events] = React.useState(() => createEventEmitter());\n return /*#__PURE__*/jsx(FloatingTreeContext.Provider, {\n value: React.useMemo(() => ({\n nodesRef,\n addNode,\n removeNode,\n events\n }), [addNode, removeNode, events]),\n children: children\n });\n}\n\nfunction createAttribute(name) {\n return \"data-floating-ui-\" + name;\n}\n\nfunction clearTimeoutIfSet(timeoutRef) {\n if (timeoutRef.current !== -1) {\n clearTimeout(timeoutRef.current);\n timeoutRef.current = -1;\n }\n}\n\nconst safePolygonIdentifier = /*#__PURE__*/createAttribute('safe-polygon');\nfunction getDelay(value, prop, pointerType) {\n if (pointerType && !isMouseLikePointerType(pointerType)) {\n return 0;\n }\n if (typeof value === 'number') {\n return value;\n }\n if (typeof value === 'function') {\n const result = value();\n if (typeof result === 'number') {\n return result;\n }\n return result == null ? void 0 : result[prop];\n }\n return value == null ? void 0 : value[prop];\n}\nfunction getRestMs(value) {\n if (typeof value === 'function') {\n return value();\n }\n return value;\n}\n/**\n * Opens the floating element while hovering over the reference element, like\n * CSS `:hover`.\n * @see https://floating-ui.com/docs/useHover\n */\nfunction useHover(context, props) {\n if (props === void 0) {\n props = {};\n }\n const {\n open,\n onOpenChange,\n dataRef,\n events,\n elements\n } = context;\n const {\n enabled = true,\n delay = 0,\n handleClose = null,\n mouseOnly = false,\n restMs = 0,\n move = true\n } = props;\n const tree = useFloatingTree();\n const parentId = useFloatingParentNodeId();\n const handleCloseRef = useLatestRef(handleClose);\n const delayRef = useLatestRef(delay);\n const openRef = useLatestRef(open);\n const restMsRef = useLatestRef(restMs);\n const pointerTypeRef = React.useRef();\n const timeoutRef = React.useRef(-1);\n const handlerRef = React.useRef();\n const restTimeoutRef = React.useRef(-1);\n const blockMouseMoveRef = React.useRef(true);\n const performedPointerEventsMutationRef = React.useRef(false);\n const unbindMouseMoveRef = React.useRef(() => {});\n const restTimeoutPendingRef = React.useRef(false);\n const isHoverOpen = useEffectEvent(() => {\n var _dataRef$current$open;\n const type = (_dataRef$current$open = dataRef.current.openEvent) == null ? void 0 : _dataRef$current$open.type;\n return (type == null ? void 0 : type.includes('mouse')) && type !== 'mousedown';\n });\n\n // When closing before opening, clear the delay timeouts to cancel it\n // from showing.\n React.useEffect(() => {\n if (!enabled) return;\n function onOpenChange(_ref) {\n let {\n open\n } = _ref;\n if (!open) {\n clearTimeoutIfSet(timeoutRef);\n clearTimeoutIfSet(restTimeoutRef);\n blockMouseMoveRef.current = true;\n restTimeoutPendingRef.current = false;\n }\n }\n events.on('openchange', onOpenChange);\n return () => {\n events.off('openchange', onOpenChange);\n };\n }, [enabled, events]);\n React.useEffect(() => {\n if (!enabled) return;\n if (!handleCloseRef.current) return;\n if (!open) return;\n function onLeave(event) {\n if (isHoverOpen()) {\n onOpenChange(false, event, 'hover');\n }\n }\n const html = getDocument$1(elements.floating).documentElement;\n html.addEventListener('mouseleave', onLeave);\n return () => {\n html.removeEventListener('mouseleave', onLeave);\n };\n }, [elements.floating, open, onOpenChange, enabled, handleCloseRef, isHoverOpen]);\n const closeWithDelay = React.useCallback(function (event, runElseBranch, reason) {\n if (runElseBranch === void 0) {\n runElseBranch = true;\n }\n if (reason === void 0) {\n reason = 'hover';\n }\n const closeDelay = getDelay(delayRef.current, 'close', pointerTypeRef.current);\n if (closeDelay && !handlerRef.current) {\n clearTimeoutIfSet(timeoutRef);\n timeoutRef.current = window.setTimeout(() => onOpenChange(false, event, reason), closeDelay);\n } else if (runElseBranch) {\n clearTimeoutIfSet(timeoutRef);\n onOpenChange(false, event, reason);\n }\n }, [delayRef, onOpenChange]);\n const cleanupMouseMoveHandler = useEffectEvent(() => {\n unbindMouseMoveRef.current();\n handlerRef.current = undefined;\n });\n const clearPointerEvents = useEffectEvent(() => {\n if (performedPointerEventsMutationRef.current) {\n const body = getDocument$1(elements.floating).body;\n body.style.pointerEvents = '';\n body.removeAttribute(safePolygonIdentifier);\n performedPointerEventsMutationRef.current = false;\n }\n });\n const isClickLikeOpenEvent = useEffectEvent(() => {\n return dataRef.current.openEvent ? ['click', 'mousedown'].includes(dataRef.current.openEvent.type) : false;\n });\n\n // Registering the mouse events on the reference directly to bypass React's\n // delegation system. If the cursor was on a disabled element and then entered\n // the reference (no gap), `mouseenter` doesn't fire in the delegation system.\n React.useEffect(() => {\n if (!enabled) return;\n function onReferenceMouseEnter(event) {\n clearTimeoutIfSet(timeoutRef);\n blockMouseMoveRef.current = false;\n if (mouseOnly && !isMouseLikePointerType(pointerTypeRef.current) || getRestMs(restMsRef.current) > 0 && !getDelay(delayRef.current, 'open')) {\n return;\n }\n const openDelay = getDelay(delayRef.current, 'open', pointerTypeRef.current);\n if (openDelay) {\n timeoutRef.current = window.setTimeout(() => {\n if (!openRef.current) {\n onOpenChange(true, event, 'hover');\n }\n }, openDelay);\n } else if (!open) {\n onOpenChange(true, event, 'hover');\n }\n }\n function onReferenceMouseLeave(event) {\n if (isClickLikeOpenEvent()) {\n clearPointerEvents();\n return;\n }\n unbindMouseMoveRef.current();\n const doc = getDocument$1(elements.floating);\n clearTimeoutIfSet(restTimeoutRef);\n restTimeoutPendingRef.current = false;\n if (handleCloseRef.current && dataRef.current.floatingContext) {\n // Prevent clearing `onScrollMouseLeave` timeout.\n if (!open) {\n clearTimeoutIfSet(timeoutRef);\n }\n handlerRef.current = handleCloseRef.current({\n ...dataRef.current.floatingContext,\n tree,\n x: event.clientX,\n y: event.clientY,\n onClose() {\n clearPointerEvents();\n cleanupMouseMoveHandler();\n if (!isClickLikeOpenEvent()) {\n closeWithDelay(event, true, 'safe-polygon');\n }\n }\n });\n const handler = handlerRef.current;\n doc.addEventListener('mousemove', handler);\n unbindMouseMoveRef.current = () => {\n doc.removeEventListener('mousemove', handler);\n };\n return;\n }\n\n // Allow interactivity without `safePolygon` on touch devices. With a\n // pointer, a short close delay is an alternative, so it should work\n // consistently.\n const shouldClose = pointerTypeRef.current === 'touch' ? !contains$1(elements.floating, event.relatedTarget) : true;\n if (shouldClose) {\n closeWithDelay(event);\n }\n }\n\n // Ensure the floating element closes after scrolling even if the pointer\n // did not move.\n // https://github.com/floating-ui/floating-ui/discussions/1692\n function onScrollMouseLeave(event) {\n if (isClickLikeOpenEvent()) return;\n if (!dataRef.current.floatingContext) return;\n handleCloseRef.current == null || handleCloseRef.current({\n ...dataRef.current.floatingContext,\n tree,\n x: event.clientX,\n y: event.clientY,\n onClose() {\n clearPointerEvents();\n cleanupMouseMoveHandler();\n if (!isClickLikeOpenEvent()) {\n closeWithDelay(event);\n }\n }\n })(event);\n }\n function onFloatingMouseEnter() {\n clearTimeoutIfSet(timeoutRef);\n }\n function onFloatingMouseLeave(event) {\n if (!isClickLikeOpenEvent()) {\n closeWithDelay(event, false);\n }\n }\n if (isElement(elements.domReference)) {\n const reference = elements.domReference;\n const floating = elements.floating;\n if (open) {\n reference.addEventListener('mouseleave', onScrollMouseLeave);\n }\n if (move) {\n reference.addEventListener('mousemove', onReferenceMouseEnter, {\n once: true\n });\n }\n reference.addEventListener('mouseenter', onReferenceMouseEnter);\n reference.addEventListener('mouseleave', onReferenceMouseLeave);\n if (floating) {\n floating.addEventListener('mouseleave', onScrollMouseLeave);\n floating.addEventListener('mouseenter', onFloatingMouseEnter);\n floating.addEventListener('mouseleave', onFloatingMouseLeave);\n }\n return () => {\n if (open) {\n reference.removeEventListener('mouseleave', onScrollMouseLeave);\n }\n if (move) {\n reference.removeEventListener('mousemove', onReferenceMouseEnter);\n }\n reference.removeEventListener('mouseenter', onReferenceMouseEnter);\n reference.removeEventListener('mouseleave', onReferenceMouseLeave);\n if (floating) {\n floating.removeEventListener('mouseleave', onScrollMouseLeave);\n floating.removeEventListener('mouseenter', onFloatingMouseEnter);\n floating.removeEventListener('mouseleave', onFloatingMouseLeave);\n }\n };\n }\n }, [elements, enabled, context, mouseOnly, move, closeWithDelay, cleanupMouseMoveHandler, clearPointerEvents, onOpenChange, open, openRef, tree, delayRef, handleCloseRef, dataRef, isClickLikeOpenEvent, restMsRef]);\n\n // Block pointer-events of every element other than the reference and floating\n // while the floating element is open and has a `handleClose` handler. Also\n // handles nested floating elements.\n // https://github.com/floating-ui/floating-ui/issues/1722\n useModernLayoutEffect(() => {\n var _handleCloseRef$curre;\n if (!enabled) return;\n if (open && (_handleCloseRef$curre = handleCloseRef.current) != null && (_handleCloseRef$curre = _handleCloseRef$curre.__options) != null && _handleCloseRef$curre.blockPointerEvents && isHoverOpen()) {\n performedPointerEventsMutationRef.current = true;\n const floatingEl = elements.floating;\n if (isElement(elements.domReference) && floatingEl) {\n var _tree$nodesRef$curren;\n const body = getDocument$1(elements.floating).body;\n body.setAttribute(safePolygonIdentifier, '');\n const ref = elements.domReference;\n const parentFloating = tree == null || (_tree$nodesRef$curren = tree.nodesRef.current.find(node => node.id === parentId)) == null || (_tree$nodesRef$curren = _tree$nodesRef$curren.context) == null ? void 0 : _tree$nodesRef$curren.elements.floating;\n if (parentFloating) {\n parentFloating.style.pointerEvents = '';\n }\n body.style.pointerEvents = 'none';\n ref.style.pointerEvents = 'auto';\n floatingEl.style.pointerEvents = 'auto';\n return () => {\n body.style.pointerEvents = '';\n ref.style.pointerEvents = '';\n floatingEl.style.pointerEvents = '';\n };\n }\n }\n }, [enabled, open, parentId, elements, tree, handleCloseRef, isHoverOpen]);\n useModernLayoutEffect(() => {\n if (!open) {\n pointerTypeRef.current = undefined;\n restTimeoutPendingRef.current = false;\n cleanupMouseMoveHandler();\n clearPointerEvents();\n }\n }, [open, cleanupMouseMoveHandler, clearPointerEvents]);\n React.useEffect(() => {\n return () => {\n cleanupMouseMoveHandler();\n clearTimeoutIfSet(timeoutRef);\n clearTimeoutIfSet(restTimeoutRef);\n clearPointerEvents();\n };\n }, [enabled, elements.domReference, cleanupMouseMoveHandler, clearPointerEvents]);\n const reference = React.useMemo(() => {\n function setPointerRef(event) {\n pointerTypeRef.current = event.pointerType;\n }\n return {\n onPointerDown: setPointerRef,\n onPointerEnter: setPointerRef,\n onMouseMove(event) {\n const {\n nativeEvent\n } = event;\n function handleMouseMove() {\n if (!blockMouseMoveRef.current && !openRef.current) {\n onOpenChange(true, nativeEvent, 'hover');\n }\n }\n if (mouseOnly && !isMouseLikePointerType(pointerTypeRef.current)) {\n return;\n }\n if (open || getRestMs(restMsRef.current) === 0) {\n return;\n }\n\n // Ignore insignificant movements to account for tremors.\n if (restTimeoutPendingRef.current && event.movementX ** 2 + event.movementY ** 2 < 2) {\n return;\n }\n clearTimeoutIfSet(restTimeoutRef);\n if (pointerTypeRef.current === 'touch') {\n handleMouseMove();\n } else {\n restTimeoutPendingRef.current = true;\n restTimeoutRef.current = window.setTimeout(handleMouseMove, getRestMs(restMsRef.current));\n }\n }\n };\n }, [mouseOnly, onOpenChange, open, openRef, restMsRef]);\n return React.useMemo(() => enabled ? {\n reference\n } : {}, [enabled, reference]);\n}\n\nconst NOOP = () => {};\nconst FloatingDelayGroupContext = /*#__PURE__*/React.createContext({\n delay: 0,\n initialDelay: 0,\n timeoutMs: 0,\n currentId: null,\n setCurrentId: NOOP,\n setState: NOOP,\n isInstantPhase: false\n});\n\n/**\n * @deprecated\n * Use the return value of `useDelayGroup()` instead.\n */\nconst useDelayGroupContext = () => React.useContext(FloatingDelayGroupContext);\n/**\n * Provides context for a group of floating elements that should share a\n * `delay`.\n * @see https://floating-ui.com/docs/FloatingDelayGroup\n */\nfunction FloatingDelayGroup(props) {\n const {\n children,\n delay,\n timeoutMs = 0\n } = props;\n const [state, setState] = React.useReducer((prev, next) => ({\n ...prev,\n ...next\n }), {\n delay,\n timeoutMs,\n initialDelay: delay,\n currentId: null,\n isInstantPhase: false\n });\n const initialCurrentIdRef = React.useRef(null);\n const setCurrentId = React.useCallback(currentId => {\n setState({\n currentId\n });\n }, []);\n useModernLayoutEffect(() => {\n if (state.currentId) {\n if (initialCurrentIdRef.current === null) {\n initialCurrentIdRef.current = state.currentId;\n } else if (!state.isInstantPhase) {\n setState({\n isInstantPhase: true\n });\n }\n } else {\n if (state.isInstantPhase) {\n setState({\n isInstantPhase: false\n });\n }\n initialCurrentIdRef.current = null;\n }\n }, [state.currentId, state.isInstantPhase]);\n return /*#__PURE__*/jsx(FloatingDelayGroupContext.Provider, {\n value: React.useMemo(() => ({\n ...state,\n setState,\n setCurrentId\n }), [state, setCurrentId]),\n children: children\n });\n}\n/**\n * Enables grouping when called inside a component that's a child of a\n * `FloatingDelayGroup`.\n * @see https://floating-ui.com/docs/FloatingDelayGroup\n */\nfunction useDelayGroup(context, options) {\n if (options === void 0) {\n options = {};\n }\n const {\n open,\n onOpenChange,\n floatingId\n } = context;\n const {\n id: optionId,\n enabled = true\n } = options;\n const id = optionId != null ? optionId : floatingId;\n const groupContext = useDelayGroupContext();\n const {\n currentId,\n setCurrentId,\n initialDelay,\n setState,\n timeoutMs\n } = groupContext;\n useModernLayoutEffect(() => {\n if (!enabled) return;\n if (!currentId) return;\n setState({\n delay: {\n open: 1,\n close: getDelay(initialDelay, 'close')\n }\n });\n if (currentId !== id) {\n onOpenChange(false);\n }\n }, [enabled, id, onOpenChange, setState, currentId, initialDelay]);\n useModernLayoutEffect(() => {\n function unset() {\n onOpenChange(false);\n setState({\n delay: initialDelay,\n currentId: null\n });\n }\n if (!enabled) return;\n if (!currentId) return;\n if (!open && currentId === id) {\n if (timeoutMs) {\n const timeout = window.setTimeout(unset, timeoutMs);\n return () => {\n clearTimeout(timeout);\n };\n }\n unset();\n }\n }, [enabled, open, setState, currentId, id, onOpenChange, initialDelay, timeoutMs]);\n useModernLayoutEffect(() => {\n if (!enabled) return;\n if (setCurrentId === NOOP || !open) return;\n setCurrentId(id);\n }, [enabled, open, setCurrentId, id]);\n return groupContext;\n}\n\nconst NextFloatingDelayGroupContext = /*#__PURE__*/React.createContext({\n hasProvider: false,\n timeoutMs: 0,\n delayRef: {\n current: 0\n },\n initialDelayRef: {\n current: 0\n },\n timeoutIdRef: {\n current: -1\n },\n currentIdRef: {\n current: null\n },\n currentContextRef: {\n current: null\n }\n});\n/**\n * Experimental next version of `FloatingDelayGroup` to become the default\n * in the future. This component is not yet stable.\n * Provides context for a group of floating elements that should share a\n * `delay`. Unlike `FloatingDelayGroup`, `useNextDelayGroup` with this\n * component does not cause a re-render of unrelated consumers of the\n * context when the delay changes.\n * @see https://floating-ui.com/docs/FloatingDelayGroup\n */\nfunction NextFloatingDelayGroup(props) {\n const {\n children,\n delay,\n timeoutMs = 0\n } = props;\n const delayRef = React.useRef(delay);\n const initialDelayRef = React.useRef(delay);\n const currentIdRef = React.useRef(null);\n const currentContextRef = React.useRef(null);\n const timeoutIdRef = React.useRef(-1);\n return /*#__PURE__*/jsx(NextFloatingDelayGroupContext.Provider, {\n value: React.useMemo(() => ({\n hasProvider: true,\n delayRef,\n initialDelayRef,\n currentIdRef,\n timeoutMs,\n currentContextRef,\n timeoutIdRef\n }), [timeoutMs]),\n children: children\n });\n}\n/**\n * Enables grouping when called inside a component that's a child of a\n * `NextFloatingDelayGroup`.\n * @see https://floating-ui.com/docs/FloatingDelayGroup\n */\nfunction useNextDelayGroup(context, options) {\n if (options === void 0) {\n options = {};\n }\n const {\n open,\n onOpenChange,\n floatingId\n } = context;\n const {\n enabled = true\n } = options;\n const groupContext = React.useContext(NextFloatingDelayGroupContext);\n const {\n currentIdRef,\n delayRef,\n timeoutMs,\n initialDelayRef,\n currentContextRef,\n hasProvider,\n timeoutIdRef\n } = groupContext;\n const [isInstantPhase, setIsInstantPhase] = React.useState(false);\n useModernLayoutEffect(() => {\n function unset() {\n var _currentContextRef$cu;\n setIsInstantPhase(false);\n (_currentContextRef$cu = currentContextRef.current) == null || _currentContextRef$cu.setIsInstantPhase(false);\n currentIdRef.current = null;\n currentContextRef.current = null;\n delayRef.current = initialDelayRef.current;\n }\n if (!enabled) return;\n if (!currentIdRef.current) return;\n if (!open && currentIdRef.current === floatingId) {\n setIsInstantPhase(false);\n if (timeoutMs) {\n timeoutIdRef.current = window.setTimeout(unset, timeoutMs);\n return () => {\n clearTimeout(timeoutIdRef.current);\n };\n }\n unset();\n }\n }, [enabled, open, floatingId, currentIdRef, delayRef, timeoutMs, initialDelayRef, currentContextRef, timeoutIdRef]);\n useModernLayoutEffect(() => {\n if (!enabled) return;\n if (!open) return;\n const prevContext = currentContextRef.current;\n const prevId = currentIdRef.current;\n currentContextRef.current = {\n onOpenChange,\n setIsInstantPhase\n };\n currentIdRef.current = floatingId;\n delayRef.current = {\n open: 0,\n close: getDelay(initialDelayRef.current, 'close')\n };\n if (prevId !== null && prevId !== floatingId) {\n clearTimeoutIfSet(timeoutIdRef);\n setIsInstantPhase(true);\n prevContext == null || prevContext.setIsInstantPhase(true);\n prevContext == null || prevContext.onOpenChange(false);\n } else {\n setIsInstantPhase(false);\n prevContext == null || prevContext.setIsInstantPhase(false);\n }\n }, [enabled, open, floatingId, onOpenChange, currentIdRef, delayRef, timeoutMs, initialDelayRef, currentContextRef, timeoutIdRef]);\n useModernLayoutEffect(() => {\n return () => {\n currentContextRef.current = null;\n };\n }, [currentContextRef]);\n return React.useMemo(() => ({\n hasProvider,\n delayRef,\n isInstantPhase\n }), [hasProvider, delayRef, isInstantPhase]);\n}\n\nlet rafId = 0;\nfunction enqueueFocus(el, options) {\n if (options === void 0) {\n options = {};\n }\n const {\n preventScroll = false,\n cancelPrevious = true,\n sync = false\n } = options;\n cancelPrevious && cancelAnimationFrame(rafId);\n const exec = () => el == null ? void 0 : el.focus({\n preventScroll\n });\n if (sync) {\n exec();\n } else {\n rafId = requestAnimationFrame(exec);\n }\n}\n\nfunction contains(parent, child) {\n if (!parent || !child) {\n return false;\n }\n const rootNode = child.getRootNode == null ? void 0 : child.getRootNode();\n\n // First, attempt with faster native method\n if (parent.contains(child)) {\n return true;\n }\n\n // then fallback to custom implementation with Shadow DOM support\n if (rootNode && isShadowRoot(rootNode)) {\n let next = child;\n while (next) {\n if (parent === next) {\n return true;\n }\n // @ts-ignore\n next = next.parentNode || next.host;\n }\n }\n\n // Give up, the result is false\n return false;\n}\nfunction getTarget(event) {\n if ('composedPath' in event) {\n return event.composedPath()[0];\n }\n\n // TS thinks `event` is of type never as it assumes all browsers support\n // `composedPath()`, but browsers without shadow DOM don't.\n return event.target;\n}\nfunction getDocument(node) {\n return (node == null ? void 0 : node.ownerDocument) || document;\n}\n\n// Modified to add conditional `aria-hidden` support:\n// https://github.com/theKashey/aria-hidden/blob/9220c8f4a4fd35f63bee5510a9f41a37264382d4/src/index.ts\nconst counters = {\n inert: /*#__PURE__*/new WeakMap(),\n 'aria-hidden': /*#__PURE__*/new WeakMap(),\n none: /*#__PURE__*/new WeakMap()\n};\nfunction getCounterMap(control) {\n if (control === 'inert') return counters.inert;\n if (control === 'aria-hidden') return counters['aria-hidden'];\n return counters.none;\n}\nlet uncontrolledElementsSet = /*#__PURE__*/new WeakSet();\nlet markerMap = {};\nlet lockCount$1 = 0;\nconst supportsInert = () => typeof HTMLElement !== 'undefined' && 'inert' in HTMLElement.prototype;\nfunction unwrapHost(node) {\n if (!node) {\n return null;\n }\n return isShadowRoot(node) ? node.host : unwrapHost(node.parentNode);\n}\nconst correctElements = (parent, targets) => targets.map(target => {\n if (parent.contains(target)) {\n return target;\n }\n const correctedTarget = unwrapHost(target);\n if (parent.contains(correctedTarget)) {\n return correctedTarget;\n }\n return null;\n}).filter(x => x != null);\nfunction applyAttributeToOthers(uncorrectedAvoidElements, body, ariaHidden, inert) {\n const markerName = 'data-floating-ui-inert';\n const controlAttribute = inert ? 'inert' : ariaHidden ? 'aria-hidden' : null;\n const avoidElements = correctElements(body, uncorrectedAvoidElements);\n const elementsToKeep = new Set();\n const elementsToStop = new Set(avoidElements);\n const hiddenElements = [];\n if (!markerMap[markerName]) {\n markerMap[markerName] = new WeakMap();\n }\n const markerCounter = markerMap[markerName];\n avoidElements.forEach(keep);\n deep(body);\n elementsToKeep.clear();\n function keep(el) {\n if (!el || elementsToKeep.has(el)) {\n return;\n }\n elementsToKeep.add(el);\n el.parentNode && keep(el.parentNode);\n }\n function deep(parent) {\n if (!parent || elementsToStop.has(parent)) {\n return;\n }\n [].forEach.call(parent.children, node => {\n if (getNodeName(node) === 'script') return;\n if (elementsToKeep.has(node)) {\n deep(node);\n } else {\n const attr = controlAttribute ? node.getAttribute(controlAttribute) : null;\n const alreadyHidden = attr !== null && attr !== 'false';\n const counterMap = getCounterMap(controlAttribute);\n const counterValue = (counterMap.get(node) || 0) + 1;\n const markerValue = (markerCounter.get(node) || 0) + 1;\n counterMap.set(node, counterValue);\n markerCounter.set(node, markerValue);\n hiddenElements.push(node);\n if (counterValue === 1 && alreadyHidden) {\n uncontrolledElementsSet.add(node);\n }\n if (markerValue === 1) {\n node.setAttribute(markerName, '');\n }\n if (!alreadyHidden && controlAttribute) {\n node.setAttribute(controlAttribute, controlAttribute === 'inert' ? '' : 'true');\n }\n }\n });\n }\n lockCount$1++;\n return () => {\n hiddenElements.forEach(element => {\n const counterMap = getCounterMap(controlAttribute);\n const currentCounterValue = counterMap.get(element) || 0;\n const counterValue = currentCounterValue - 1;\n const markerValue = (markerCounter.get(element) || 0) - 1;\n counterMap.set(element, counterValue);\n markerCounter.set(element, markerValue);\n if (!counterValue) {\n if (!uncontrolledElementsSet.has(element) && controlAttribute) {\n element.removeAttribute(controlAttribute);\n }\n uncontrolledElementsSet.delete(element);\n }\n if (!markerValue) {\n element.removeAttribute(markerName);\n }\n });\n lockCount$1--;\n if (!lockCount$1) {\n counters.inert = new WeakMap();\n counters['aria-hidden'] = new WeakMap();\n counters.none = new WeakMap();\n uncontrolledElementsSet = new WeakSet();\n markerMap = {};\n }\n };\n}\nfunction markOthers(avoidElements, ariaHidden, inert) {\n if (ariaHidden === void 0) {\n ariaHidden = false;\n }\n if (inert === void 0) {\n inert = false;\n }\n const body = getDocument(avoidElements[0]).body;\n return applyAttributeToOthers(avoidElements.concat(Array.from(body.querySelectorAll('[aria-live],[role=\"status\"],output'))), body, ariaHidden, inert);\n}\n\nconst HIDDEN_STYLES = {\n border: 0,\n clip: 'rect(0 0 0 0)',\n height: '1px',\n margin: '-1px',\n overflow: 'hidden',\n padding: 0,\n position: 'fixed',\n whiteSpace: 'nowrap',\n width: '1px',\n top: 0,\n left: 0\n};\nconst FocusGuard = /*#__PURE__*/React.forwardRef(function FocusGuard(props, ref) {\n const [role, setRole] = React.useState();\n useModernLayoutEffect(() => {\n if (isSafari()) {\n // Unlike other screen readers such as NVDA and JAWS, the virtual cursor\n // on VoiceOver does trigger the onFocus event, so we can use the focus\n // trap element. On Safari, only buttons trigger the onFocus event.\n // NB: \"group\" role in the Sandbox no longer appears to work, must be a\n // button role.\n setRole('button');\n }\n }, []);\n const restProps = {\n ref,\n tabIndex: 0,\n // Role is only for VoiceOver\n role,\n 'aria-hidden': role ? undefined : true,\n [createAttribute('focus-guard')]: '',\n style: HIDDEN_STYLES\n };\n return /*#__PURE__*/jsx(\"span\", {\n ...props,\n ...restProps\n });\n});\n\nconst HIDDEN_OWNER_STYLES = {\n clipPath: 'inset(50%)',\n position: 'fixed',\n top: 0,\n left: 0\n};\nconst PortalContext = /*#__PURE__*/React.createContext(null);\nconst attr = /*#__PURE__*/createAttribute('portal');\n/**\n * @see https://floating-ui.com/docs/FloatingPortal#usefloatingportalnode\n */\nfunction useFloatingPortalNode(props) {\n if (props === void 0) {\n props = {};\n }\n const {\n id,\n root\n } = props;\n const uniqueId = useId();\n const portalContext = usePortalContext();\n const [portalNode, setPortalNode] = React.useState(null);\n const portalNodeRef = React.useRef(null);\n useModernLayoutEffect(() => {\n return () => {\n portalNode == null || portalNode.remove();\n // Allow the subsequent layout effects to create a new node on updates.\n // The portal node will still be cleaned up on unmount.\n // https://github.com/floating-ui/floating-ui/issues/2454\n queueMicrotask(() => {\n portalNodeRef.current = null;\n });\n };\n }, [portalNode]);\n useModernLayoutEffect(() => {\n // Wait for the uniqueId to be generated before creating the portal node in\n // React <18 (using `useFloatingId` instead of the native `useId`).\n // https://github.com/floating-ui/floating-ui/issues/2778\n if (!uniqueId) return;\n if (portalNodeRef.current) return;\n const existingIdRoot = id ? document.getElementById(id) : null;\n if (!existingIdRoot) return;\n const subRoot = document.createElement('div');\n subRoot.id = uniqueId;\n subRoot.setAttribute(attr, '');\n existingIdRoot.appendChild(subRoot);\n portalNodeRef.current = subRoot;\n setPortalNode(subRoot);\n }, [id, uniqueId]);\n useModernLayoutEffect(() => {\n // Wait for the root to exist before creating the portal node. The root must\n // be stored in state, not a ref, for this to work reactively.\n if (root === null) return;\n if (!uniqueId) return;\n if (portalNodeRef.current) return;\n let container = root || (portalContext == null ? void 0 : portalContext.portalNode);\n if (container && !isNode(container)) container = container.current;\n container = container || document.body;\n let idWrapper = null;\n if (id) {\n idWrapper = document.createElement('div');\n idWrapper.id = id;\n container.appendChild(idWrapper);\n }\n const subRoot = document.createElement('div');\n subRoot.id = uniqueId;\n subRoot.setAttribute(attr, '');\n container = idWrapper || container;\n container.appendChild(subRoot);\n portalNodeRef.current = subRoot;\n setPortalNode(subRoot);\n }, [id, root, uniqueId, portalContext]);\n return portalNode;\n}\n/**\n * Portals the floating element into a given container element — by default,\n * outside of the app root and into the body.\n * This is necessary to ensure the floating element can appear outside any\n * potential parent containers that cause clipping (such as `overflow: hidden`),\n * while retaining its location in the React tree.\n * @see https://floating-ui.com/docs/FloatingPortal\n */\nfunction FloatingPortal(props) {\n const {\n children,\n id,\n root,\n preserveTabOrder = true\n } = props;\n const portalNode = useFloatingPortalNode({\n id,\n root\n });\n const [focusManagerState, setFocusManagerState] = React.useState(null);\n const beforeOutsideRef = React.useRef(null);\n const afterOutsideRef = React.useRef(null);\n const beforeInsideRef = React.useRef(null);\n const afterInsideRef = React.useRef(null);\n const modal = focusManagerState == null ? void 0 : focusManagerState.modal;\n const open = focusManagerState == null ? void 0 : focusManagerState.open;\n const shouldRenderGuards =\n // The FocusManager and therefore floating element are currently open/\n // rendered.\n !!focusManagerState &&\n // Guards are only for non-modal focus management.\n !focusManagerState.modal &&\n // Don't render if unmount is transitioning.\n focusManagerState.open && preserveTabOrder && !!(root || portalNode);\n\n // https://codesandbox.io/s/tabbable-portal-f4tng?file=/src/TabbablePortal.tsx\n React.useEffect(() => {\n if (!portalNode || !preserveTabOrder || modal) {\n return;\n }\n\n // Make sure elements inside the portal element are tabbable only when the\n // portal has already been focused, either by tabbing into a focus trap\n // element outside or using the mouse.\n function onFocus(event) {\n if (portalNode && isOutsideEvent(event)) {\n const focusing = event.type === 'focusin';\n const manageFocus = focusing ? enableFocusInside : disableFocusInside;\n manageFocus(portalNode);\n }\n }\n // Listen to the event on the capture phase so they run before the focus\n // trap elements onFocus prop is called.\n portalNode.addEventListener('focusin', onFocus, true);\n portalNode.addEventListener('focusout', onFocus, true);\n return () => {\n portalNode.removeEventListener('focusin', onFocus, true);\n portalNode.removeEventListener('focusout', onFocus, true);\n };\n }, [portalNode, preserveTabOrder, modal]);\n React.useEffect(() => {\n if (!portalNode) return;\n if (open) return;\n enableFocusInside(portalNode);\n }, [open, portalNode]);\n return /*#__PURE__*/jsxs(PortalContext.Provider, {\n value: React.useMemo(() => ({\n preserveTabOrder,\n beforeOutsideRef,\n afterOutsideRef,\n beforeInsideRef,\n afterInsideRef,\n portalNode,\n setFocusManagerState\n }), [preserveTabOrder, portalNode]),\n children: [shouldRenderGuards && portalNode && /*#__PURE__*/jsx(FocusGuard, {\n \"data-type\": \"outside\",\n ref: beforeOutsideRef,\n onFocus: event => {\n if (isOutsideEvent(event, portalNode)) {\n var _beforeInsideRef$curr;\n (_beforeInsideRef$curr = beforeInsideRef.current) == null || _beforeInsideRef$curr.focus();\n } else {\n const domReference = focusManagerState ? focusManagerState.domReference : null;\n const prevTabbable = getPreviousTabbable(domReference);\n prevTabbable == null || prevTabbable.focus();\n }\n }\n }), shouldRenderGuards && portalNode && /*#__PURE__*/jsx(\"span\", {\n \"aria-owns\": portalNode.id,\n style: HIDDEN_OWNER_STYLES\n }), portalNode && /*#__PURE__*/ReactDOM.createPortal(children, portalNode), shouldRenderGuards && portalNode && /*#__PURE__*/jsx(FocusGuard, {\n \"data-type\": \"outside\",\n ref: afterOutsideRef,\n onFocus: event => {\n if (isOutsideEvent(event, portalNode)) {\n var _afterInsideRef$curre;\n (_afterInsideRef$curre = afterInsideRef.current) == null || _afterInsideRef$curre.focus();\n } else {\n const domReference = focusManagerState ? focusManagerState.domReference : null;\n const nextTabbable = getNextTabbable(domReference);\n nextTabbable == null || nextTabbable.focus();\n (focusManagerState == null ? void 0 : focusManagerState.closeOnFocusOut) && (focusManagerState == null ? void 0 : focusManagerState.onOpenChange(false, event.nativeEvent, 'focus-out'));\n }\n }\n })]\n });\n}\nconst usePortalContext = () => React.useContext(PortalContext);\n\nfunction useLiteMergeRefs(refs) {\n return React.useMemo(() => {\n return value => {\n refs.forEach(ref => {\n if (ref) {\n ref.current = value;\n }\n });\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, refs);\n}\n\nconst LIST_LIMIT = 20;\nlet previouslyFocusedElements = [];\nfunction clearDisconnectedPreviouslyFocusedElements() {\n previouslyFocusedElements = previouslyFocusedElements.filter(elementRef => {\n var _elementRef$deref;\n return (_elementRef$deref = elementRef.deref()) == null ? void 0 : _elementRef$deref.isConnected;\n });\n}\nfunction addPreviouslyFocusedElement(element) {\n clearDisconnectedPreviouslyFocusedElements();\n if (element && getNodeName(element) !== 'body') {\n previouslyFocusedElements.push(new WeakRef(element));\n if (previouslyFocusedElements.length > LIST_LIMIT) {\n previouslyFocusedElements = previouslyFocusedElements.slice(-LIST_LIMIT);\n }\n }\n}\nfunction getPreviouslyFocusedElement() {\n clearDisconnectedPreviouslyFocusedElements();\n const elementRef = previouslyFocusedElements[previouslyFocusedElements.length - 1];\n return elementRef == null ? void 0 : elementRef.deref();\n}\nfunction getFirstTabbableElement(container) {\n const tabbableOptions = getTabbableOptions();\n if (isTabbable(container, tabbableOptions)) {\n return container;\n }\n return tabbable(container, tabbableOptions)[0] || container;\n}\nfunction handleTabIndex(floatingFocusElement, orderRef) {\n var _floatingFocusElement;\n if (!orderRef.current.includes('floating') && !((_floatingFocusElement = floatingFocusElement.getAttribute('role')) != null && _floatingFocusElement.includes('dialog'))) {\n return;\n }\n const options = getTabbableOptions();\n const focusableElements = focusable(floatingFocusElement, options);\n const tabbableContent = focusableElements.filter(element => {\n const dataTabIndex = element.getAttribute('data-tabindex') || '';\n return isTabbable(element, options) || element.hasAttribute('data-tabindex') && !dataTabIndex.startsWith('-');\n });\n const tabIndex = floatingFocusElement.getAttribute('tabindex');\n if (orderRef.current.includes('floating') || tabbableContent.length === 0) {\n if (tabIndex !== '0') {\n floatingFocusElement.setAttribute('tabindex', '0');\n }\n } else if (tabIndex !== '-1' || floatingFocusElement.hasAttribute('data-tabindex') && floatingFocusElement.getAttribute('data-tabindex') !== '-1') {\n floatingFocusElement.setAttribute('tabindex', '-1');\n floatingFocusElement.setAttribute('data-tabindex', '-1');\n }\n}\nconst VisuallyHiddenDismiss = /*#__PURE__*/React.forwardRef(function VisuallyHiddenDismiss(props, ref) {\n return /*#__PURE__*/jsx(\"button\", {\n ...props,\n type: \"button\",\n ref: ref,\n tabIndex: -1,\n style: HIDDEN_STYLES\n });\n});\n/**\n * Provides focus management for the floating element.\n * @see https://floating-ui.com/docs/FloatingFocusManager\n */\nfunction FloatingFocusManager(props) {\n const {\n context,\n children,\n disabled = false,\n order = ['content'],\n guards: _guards = true,\n initialFocus = 0,\n returnFocus = true,\n restoreFocus = false,\n modal = true,\n visuallyHiddenDismiss = false,\n closeOnFocusOut = true,\n outsideElementsInert = false,\n getInsideElements: _getInsideElements = () => []\n } = props;\n const {\n open,\n onOpenChange,\n events,\n dataRef,\n elements: {\n domReference,\n floating\n }\n } = context;\n const getNodeId = useEffectEvent(() => {\n var _dataRef$current$floa;\n return (_dataRef$current$floa = dataRef.current.floatingContext) == null ? void 0 : _dataRef$current$floa.nodeId;\n });\n const getInsideElements = useEffectEvent(_getInsideElements);\n const ignoreInitialFocus = typeof initialFocus === 'number' && initialFocus < 0;\n // If the reference is a combobox and is typeable (e.g. input/textarea),\n // there are different focus semantics. The guards should not be rendered, but\n // aria-hidden should be applied to all nodes still. Further, the visually\n // hidden dismiss button should only appear at the end of the list, not the\n // start.\n const isUntrappedTypeableCombobox = isTypeableCombobox(domReference) && ignoreInitialFocus;\n\n // Force the guards to be rendered if the `inert` attribute is not supported.\n const inertSupported = supportsInert();\n const guards = inertSupported ? _guards : true;\n const useInert = !guards || inertSupported && outsideElementsInert;\n const orderRef = useLatestRef(order);\n const initialFocusRef = useLatestRef(initialFocus);\n const returnFocusRef = useLatestRef(returnFocus);\n const tree = useFloatingTree();\n const portalContext = usePortalContext();\n const startDismissButtonRef = React.useRef(null);\n const endDismissButtonRef = React.useRef(null);\n const preventReturnFocusRef = React.useRef(false);\n const isPointerDownRef = React.useRef(false);\n const tabbableIndexRef = React.useRef(-1);\n const blurTimeoutRef = React.useRef(-1);\n const isInsidePortal = portalContext != null;\n const floatingFocusElement = getFloatingFocusElement(floating);\n const getTabbableContent = useEffectEvent(function (container) {\n if (container === void 0) {\n container = floatingFocusElement;\n }\n return container ? tabbable(container, getTabbableOptions()) : [];\n });\n const getTabbableElements = useEffectEvent(container => {\n const content = getTabbableContent(container);\n return orderRef.current.map(type => {\n if (domReference && type === 'reference') {\n return domReference;\n }\n if (floatingFocusElement && type === 'floating') {\n return floatingFocusElement;\n }\n return content;\n }).filter(Boolean).flat();\n });\n React.useEffect(() => {\n if (disabled) return;\n if (!modal) return;\n function onKeyDown(event) {\n if (event.key === 'Tab') {\n // The focus guards have nothing to focus, so we need to stop the event.\n if (contains$1(floatingFocusElement, activeElement(getDocument$1(floatingFocusElement))) && getTabbableContent().length === 0 && !isUntrappedTypeableCombobox) {\n stopEvent(event);\n }\n const els = getTabbableElements();\n const target = getTarget$1(event);\n if (orderRef.current[0] === 'reference' && target === domReference) {\n stopEvent(event);\n if (event.shiftKey) {\n enqueueFocus(els[els.length - 1]);\n } else {\n enqueueFocus(els[1]);\n }\n }\n if (orderRef.current[1] === 'floating' && target === floatingFocusElement && event.shiftKey) {\n stopEvent(event);\n enqueueFocus(els[0]);\n }\n }\n }\n const doc = getDocument$1(floatingFocusElement);\n doc.addEventListener('keydown', onKeyDown);\n return () => {\n doc.removeEventListener('keydown', onKeyDown);\n };\n }, [disabled, domReference, floatingFocusElement, modal, orderRef, isUntrappedTypeableCombobox, getTabbableContent, getTabbableElements]);\n React.useEffect(() => {\n if (disabled) return;\n if (!floating) return;\n function handleFocusIn(event) {\n const target = getTarget$1(event);\n const tabbableContent = getTabbableContent();\n const tabbableIndex = tabbableContent.indexOf(target);\n if (tabbableIndex !== -1) {\n tabbableIndexRef.current = tabbableIndex;\n }\n }\n floating.addEventListener('focusin', handleFocusIn);\n return () => {\n floating.removeEventListener('focusin', handleFocusIn);\n };\n }, [disabled, floating, getTabbableContent]);\n React.useEffect(() => {\n if (disabled) return;\n if (!closeOnFocusOut) return;\n\n // In Safari, buttons lose focus when pressing them.\n function handlePointerDown() {\n isPointerDownRef.current = true;\n setTimeout(() => {\n isPointerDownRef.current = false;\n });\n }\n function handleFocusOutside(event) {\n const relatedTarget = event.relatedTarget;\n const currentTarget = event.currentTarget;\n const target = getTarget$1(event);\n queueMicrotask(() => {\n const nodeId = getNodeId();\n const movedToUnrelatedNode = !(contains$1(domReference, relatedTarget) || contains$1(floating, relatedTarget) || contains$1(relatedTarget, floating) || contains$1(portalContext == null ? void 0 : portalContext.portalNode, relatedTarget) || relatedTarget != null && relatedTarget.hasAttribute(createAttribute('focus-guard')) || tree && (getNodeChildren$1(tree.nodesRef.current, nodeId).find(node => {\n var _node$context, _node$context2;\n return contains$1((_node$context = node.context) == null ? void 0 : _node$context.elements.floating, relatedTarget) || contains$1((_node$context2 = node.context) == null ? void 0 : _node$context2.elements.domReference, relatedTarget);\n }) || getNodeAncestors(tree.nodesRef.current, nodeId).find(node => {\n var _node$context3, _node$context4, _node$context5;\n return [(_node$context3 = node.context) == null ? void 0 : _node$context3.elements.floating, getFloatingFocusElement((_node$context4 = node.context) == null ? void 0 : _node$context4.elements.floating)].includes(relatedTarget) || ((_node$context5 = node.context) == null ? void 0 : _node$context5.elements.domReference) === relatedTarget;\n })));\n if (currentTarget === domReference && floatingFocusElement) {\n handleTabIndex(floatingFocusElement, orderRef);\n }\n\n // Restore focus to the previous tabbable element index to prevent\n // focus from being lost outside the floating tree.\n if (restoreFocus && currentTarget !== domReference && !(target != null && target.isConnected) && activeElement(getDocument$1(floatingFocusElement)) === getDocument$1(floatingFocusElement).body) {\n // Let `FloatingPortal` effect knows that focus is still inside the\n // floating tree.\n if (isHTMLElement(floatingFocusElement)) {\n floatingFocusElement.focus();\n }\n const prevTabbableIndex = tabbableIndexRef.current;\n const tabbableContent = getTabbableContent();\n const nodeToFocus = tabbableContent[prevTabbableIndex] || tabbableContent[tabbableContent.length - 1] || floatingFocusElement;\n if (isHTMLElement(nodeToFocus)) {\n nodeToFocus.focus();\n }\n }\n\n // https://github.com/floating-ui/floating-ui/issues/3060\n if (dataRef.current.insideReactTree) {\n dataRef.current.insideReactTree = false;\n return;\n }\n\n // Focus did not move inside the floating tree, and there are no tabbable\n // portal guards to handle closing.\n if ((isUntrappedTypeableCombobox ? true : !modal) && relatedTarget && movedToUnrelatedNode && !isPointerDownRef.current &&\n // Fix React 18 Strict Mode returnFocus due to double rendering.\n relatedTarget !== getPreviouslyFocusedElement()) {\n preventReturnFocusRef.current = true;\n onOpenChange(false, event, 'focus-out');\n }\n });\n }\n const shouldHandleBlurCapture = Boolean(!tree && portalContext);\n function markInsideReactTree() {\n clearTimeoutIfSet(blurTimeoutRef);\n dataRef.current.insideReactTree = true;\n blurTimeoutRef.current = window.setTimeout(() => {\n dataRef.current.insideReactTree = false;\n });\n }\n if (floating && isHTMLElement(domReference)) {\n domReference.addEventListener('focusout', handleFocusOutside);\n domReference.addEventListener('pointerdown', handlePointerDown);\n floating.addEventListener('focusout', handleFocusOutside);\n if (shouldHandleBlurCapture) {\n floating.addEventListener('focusout', markInsideReactTree, true);\n }\n return () => {\n domReference.removeEventListener('focusout', handleFocusOutside);\n domReference.removeEventListener('pointerdown', handlePointerDown);\n floating.removeEventListener('focusout', handleFocusOutside);\n if (shouldHandleBlurCapture) {\n floating.removeEventListener('focusout', markInsideReactTree, true);\n }\n };\n }\n }, [disabled, domReference, floating, floatingFocusElement, modal, tree, portalContext, onOpenChange, closeOnFocusOut, restoreFocus, getTabbableContent, isUntrappedTypeableCombobox, getNodeId, orderRef, dataRef]);\n const beforeGuardRef = React.useRef(null);\n const afterGuardRef = React.useRef(null);\n const mergedBeforeGuardRef = useLiteMergeRefs([beforeGuardRef, portalContext == null ? void 0 : portalContext.beforeInsideRef]);\n const mergedAfterGuardRef = useLiteMergeRefs([afterGuardRef, portalContext == null ? void 0 : portalContext.afterInsideRef]);\n React.useEffect(() => {\n var _portalContext$portal, _ancestors$find;\n if (disabled) return;\n if (!floating) return;\n\n // Don't hide portals nested within the parent portal.\n const portalNodes = Array.from((portalContext == null || (_portalContext$portal = portalContext.portalNode) == null ? void 0 : _portalContext$portal.querySelectorAll(\"[\" + createAttribute('portal') + \"]\")) || []);\n const ancestors = tree ? getNodeAncestors(tree.nodesRef.current, getNodeId()) : [];\n const rootAncestorComboboxDomReference = (_ancestors$find = ancestors.find(node => {\n var _node$context6;\n return isTypeableCombobox(((_node$context6 = node.context) == null ? void 0 : _node$context6.elements.domReference) || null);\n })) == null || (_ancestors$find = _ancestors$find.context) == null ? void 0 : _ancestors$find.elements.domReference;\n const insideElements = [floating, rootAncestorComboboxDomReference, ...portalNodes, ...getInsideElements(), startDismissButtonRef.current, endDismissButtonRef.current, beforeGuardRef.current, afterGuardRef.current, portalContext == null ? void 0 : portalContext.beforeOutsideRef.current, portalContext == null ? void 0 : portalContext.afterOutsideRef.current, orderRef.current.includes('reference') || isUntrappedTypeableCombobox ? domReference : null].filter(x => x != null);\n const cleanup = modal || isUntrappedTypeableCombobox ? markOthers(insideElements, !useInert, useInert) : markOthers(insideElements);\n return () => {\n cleanup();\n };\n }, [disabled, domReference, floating, modal, orderRef, portalContext, isUntrappedTypeableCombobox, guards, useInert, tree, getNodeId, getInsideElements]);\n useModernLayoutEffect(() => {\n if (disabled || !isHTMLElement(floatingFocusElement)) return;\n const doc = getDocument$1(floatingFocusElement);\n const previouslyFocusedElement = activeElement(doc);\n\n // Wait for any layout effect state setters to execute to set `tabIndex`.\n queueMicrotask(() => {\n const focusableElements = getTabbableElements(floatingFocusElement);\n const initialFocusValue = initialFocusRef.current;\n const elToFocus = (typeof initialFocusValue === 'number' ? focusableElements[initialFocusValue] : initialFocusValue.current) || floatingFocusElement;\n const focusAlreadyInsideFloatingEl = contains$1(floatingFocusElement, previouslyFocusedElement);\n if (!ignoreInitialFocus && !focusAlreadyInsideFloatingEl && open) {\n enqueueFocus(elToFocus, {\n preventScroll: elToFocus === floatingFocusElement\n });\n }\n });\n }, [disabled, open, floatingFocusElement, ignoreInitialFocus, getTabbableElements, initialFocusRef]);\n useModernLayoutEffect(() => {\n if (disabled || !floatingFocusElement) return;\n const doc = getDocument$1(floatingFocusElement);\n const previouslyFocusedElement = activeElement(doc);\n addPreviouslyFocusedElement(previouslyFocusedElement);\n\n // Dismissing via outside press should always ignore `returnFocus` to\n // prevent unwanted scrolling.\n function onOpenChange(_ref) {\n let {\n reason,\n event,\n nested\n } = _ref;\n if (['hover', 'safe-polygon'].includes(reason) && event.type === 'mouseleave') {\n preventReturnFocusRef.current = true;\n }\n if (reason !== 'outside-press') return;\n if (nested) {\n preventReturnFocusRef.current = false;\n } else if (isVirtualClick(event) || isVirtualPointerEvent(event)) {\n preventReturnFocusRef.current = false;\n } else {\n let isPreventScrollSupported = false;\n document.createElement('div').focus({\n get preventScroll() {\n isPreventScrollSupported = true;\n return false;\n }\n });\n if (isPreventScrollSupported) {\n preventReturnFocusRef.current = false;\n } else {\n preventReturnFocusRef.current = true;\n }\n }\n }\n events.on('openchange', onOpenChange);\n const fallbackEl = doc.createElement('span');\n fallbackEl.setAttribute('tabindex', '-1');\n fallbackEl.setAttribute('aria-hidden', 'true');\n Object.assign(fallbackEl.style, HIDDEN_STYLES);\n if (isInsidePortal && domReference) {\n domReference.insertAdjacentElement('afterend', fallbackEl);\n }\n function getReturnElement() {\n if (typeof returnFocusRef.current === 'boolean') {\n const el = domReference || getPreviouslyFocusedElement();\n return el && el.isConnected ? el : fallbackEl;\n }\n return returnFocusRef.current.current || fallbackEl;\n }\n return () => {\n events.off('openchange', onOpenChange);\n const activeEl = activeElement(doc);\n const isFocusInsideFloatingTree = contains$1(floating, activeEl) || tree && getNodeChildren$1(tree.nodesRef.current, getNodeId(), false).some(node => {\n var _node$context7;\n return contains$1((_node$context7 = node.context) == null ? void 0 : _node$context7.elements.floating, activeEl);\n });\n const returnElement = getReturnElement();\n queueMicrotask(() => {\n // This is `returnElement`, if it's tabbable, or its first tabbable child.\n const tabbableReturnElement = getFirstTabbableElement(returnElement);\n if (\n // eslint-disable-next-line react-hooks/exhaustive-deps\n returnFocusRef.current && !preventReturnFocusRef.current && isHTMLElement(tabbableReturnElement) && (\n // If the focus moved somewhere else after mount, avoid returning focus\n // since it likely entered a different element which should be\n // respected: https://github.com/floating-ui/floating-ui/issues/2607\n tabbableReturnElement !== activeEl && activeEl !== doc.body ? isFocusInsideFloatingTree : true)) {\n tabbableReturnElement.focus({\n preventScroll: true\n });\n }\n fallbackEl.remove();\n });\n };\n }, [disabled, floating, floatingFocusElement, returnFocusRef, dataRef, events, tree, isInsidePortal, domReference, getNodeId]);\n React.useEffect(() => {\n // The `returnFocus` cleanup behavior is inside a microtask; ensure we\n // wait for it to complete before resetting the flag.\n queueMicrotask(() => {\n preventReturnFocusRef.current = false;\n });\n return () => {\n queueMicrotask(clearDisconnectedPreviouslyFocusedElements);\n };\n }, [disabled]);\n\n // Synchronize the `context` & `modal` value to the FloatingPortal context.\n // It will decide whether or not it needs to render its own guards.\n useModernLayoutEffect(() => {\n if (disabled) return;\n if (!portalContext) return;\n portalContext.setFocusManagerState({\n modal,\n closeOnFocusOut,\n open,\n onOpenChange,\n domReference\n });\n return () => {\n portalContext.setFocusManagerState(null);\n };\n }, [disabled, portalContext, modal, open, onOpenChange, closeOnFocusOut, domReference]);\n useModernLayoutEffect(() => {\n if (disabled) return;\n if (!floatingFocusElement) return;\n handleTabIndex(floatingFocusElement, orderRef);\n }, [disabled, floatingFocusElement, orderRef]);\n function renderDismissButton(location) {\n if (disabled || !visuallyHiddenDismiss || !modal) {\n return null;\n }\n return /*#__PURE__*/jsx(VisuallyHiddenDismiss, {\n ref: location === 'start' ? startDismissButtonRef : endDismissButtonRef,\n onClick: event => onOpenChange(false, event.nativeEvent),\n children: typeof visuallyHiddenDismiss === 'string' ? visuallyHiddenDismiss : 'Dismiss'\n });\n }\n const shouldRenderGuards = !disabled && guards && (modal ? !isUntrappedTypeableCombobox : true) && (isInsidePortal || modal);\n return /*#__PURE__*/jsxs(Fragment, {\n children: [shouldRenderGuards && /*#__PURE__*/jsx(FocusGuard, {\n \"data-type\": \"inside\",\n ref: mergedBeforeGuardRef,\n onFocus: event => {\n if (modal) {\n const els = getTabbableElements();\n enqueueFocus(order[0] === 'reference' ? els[0] : els[els.length - 1]);\n } else if (portalContext != null && portalContext.preserveTabOrder && portalContext.portalNode) {\n preventReturnFocusRef.current = false;\n if (isOutsideEvent(event, portalContext.portalNode)) {\n const nextTabbable = getNextTabbable(domReference);\n nextTabbable == null || nextTabbable.focus();\n } else {\n var _portalContext$before;\n (_portalContext$before = portalContext.beforeOutsideRef.current) == null || _portalContext$before.focus();\n }\n }\n }\n }), !isUntrappedTypeableCombobox && renderDismissButton('start'), children, renderDismissButton('end'), shouldRenderGuards && /*#__PURE__*/jsx(FocusGuard, {\n \"data-type\": \"inside\",\n ref: mergedAfterGuardRef,\n onFocus: event => {\n if (modal) {\n enqueueFocus(getTabbableElements()[0]);\n } else if (portalContext != null && portalContext.preserveTabOrder && portalContext.portalNode) {\n if (closeOnFocusOut) {\n preventReturnFocusRef.current = true;\n }\n if (isOutsideEvent(event, portalContext.portalNode)) {\n const prevTabbable = getPreviousTabbable(domReference);\n prevTabbable == null || prevTabbable.focus();\n } else {\n var _portalContext$afterO;\n (_portalContext$afterO = portalContext.afterOutsideRef.current) == null || _portalContext$afterO.focus();\n }\n }\n }\n })]\n });\n}\n\nlet lockCount = 0;\nconst scrollbarProperty = '--floating-ui-scrollbar-width';\nfunction enableScrollLock() {\n const platform = getPlatform();\n const isIOS = /iP(hone|ad|od)|iOS/.test(platform) ||\n // iPads can claim to be MacIntel\n platform === 'MacIntel' && navigator.maxTouchPoints > 1;\n const bodyStyle = document.body.style;\n // RTL <body> scrollbar\n const scrollbarX = Math.round(document.documentElement.getBoundingClientRect().left) + document.documentElement.scrollLeft;\n const paddingProp = scrollbarX ? 'paddingLeft' : 'paddingRight';\n const scrollbarWidth = window.innerWidth - document.documentElement.clientWidth;\n const scrollX = bodyStyle.left ? parseFloat(bodyStyle.left) : window.scrollX;\n const scrollY = bodyStyle.top ? parseFloat(bodyStyle.top) : window.scrollY;\n bodyStyle.overflow = 'hidden';\n bodyStyle.setProperty(scrollbarProperty, scrollbarWidth + \"px\");\n if (scrollbarWidth) {\n bodyStyle[paddingProp] = scrollbarWidth + \"px\";\n }\n\n // Only iOS doesn't respect `overflow: hidden` on document.body, and this\n // technique has fewer side effects.\n if (isIOS) {\n var _window$visualViewpor, _window$visualViewpor2;\n // iOS 12 does not support `visualViewport`.\n const offsetLeft = ((_window$visualViewpor = window.visualViewport) == null ? void 0 : _window$visualViewpor.offsetLeft) || 0;\n const offsetTop = ((_window$visualViewpor2 = window.visualViewport) == null ? void 0 : _window$visualViewpor2.offsetTop) || 0;\n Object.assign(bodyStyle, {\n position: 'fixed',\n top: -(scrollY - Math.floor(offsetTop)) + \"px\",\n left: -(scrollX - Math.floor(offsetLeft)) + \"px\",\n right: '0'\n });\n }\n return () => {\n Object.assign(bodyStyle, {\n overflow: '',\n [paddingProp]: ''\n });\n bodyStyle.removeProperty(scrollbarProperty);\n if (isIOS) {\n Object.assign(bodyStyle, {\n position: '',\n top: '',\n left: '',\n right: ''\n });\n window.scrollTo(scrollX, scrollY);\n }\n };\n}\nlet cleanup = () => {};\n\n/**\n * Provides base styling for a fixed overlay element to dim content or block\n * pointer events behind a floating element.\n * It's a regular `<div>`, so it can be styled via any CSS solution you prefer.\n * @see https://floating-ui.com/docs/FloatingOverlay\n */\nconst FloatingOverlay = /*#__PURE__*/React.forwardRef(function FloatingOverlay(props, ref) {\n const {\n lockScroll = false,\n ...rest\n } = props;\n useModernLayoutEffect(() => {\n if (!lockScroll) return;\n lockCount++;\n if (lockCount === 1) {\n cleanup = enableScrollLock();\n }\n return () => {\n lockCount--;\n if (lockCount === 0) {\n cleanup();\n }\n };\n }, [lockScroll]);\n return /*#__PURE__*/jsx(\"div\", {\n ref: ref,\n ...rest,\n style: {\n position: 'fixed',\n overflow: 'auto',\n top: 0,\n right: 0,\n bottom: 0,\n left: 0,\n ...rest.style\n }\n });\n});\n\nfunction isButtonTarget(event) {\n return isHTMLElement(event.target) && event.target.tagName === 'BUTTON';\n}\nfunction isAnchorTarget(event) {\n return isHTMLElement(event.target) && event.target.tagName === 'A';\n}\nfunction isSpaceIgnored(element) {\n return isTypeableElement(element);\n}\n/**\n * Opens or closes the floating element when clicking the reference element.\n * @see https://floating-ui.com/docs/useClick\n */\nfunction useClick(context, props) {\n if (props === void 0) {\n props = {};\n }\n const {\n open,\n onOpenChange,\n dataRef,\n elements: {\n domReference\n }\n } = context;\n const {\n enabled = true,\n event: eventOption = 'click',\n toggle = true,\n ignoreMouse = false,\n keyboardHandlers = true,\n stickIfOpen = true\n } = props;\n const pointerTypeRef = React.useRef();\n const didKeyDownRef = React.useRef(false);\n const reference = React.useMemo(() => ({\n onPointerDown(event) {\n pointerTypeRef.current = event.pointerType;\n },\n onMouseDown(event) {\n const pointerType = pointerTypeRef.current;\n\n // Ignore all buttons except for the \"main\" button.\n // https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/button\n if (event.button !== 0) return;\n if (eventOption === 'click') return;\n if (isMouseLikePointerType(pointerType, true) && ignoreMouse) return;\n if (open && toggle && (dataRef.current.openEvent && stickIfOpen ? dataRef.current.openEvent.type === 'mousedown' : true)) {\n onOpenChange(false, event.nativeEvent, 'click');\n } else {\n // Prevent stealing focus from the floating element\n event.preventDefault();\n onOpenChange(true, event.nativeEvent, 'click');\n }\n },\n onClick(event) {\n const pointerType = pointerTypeRef.current;\n if (eventOption === 'mousedown' && pointerTypeRef.current) {\n pointerTypeRef.current = undefined;\n return;\n }\n if (isMouseLikePointerType(pointerType, true) && ignoreMouse) return;\n if (open && toggle && (dataRef.current.openEvent && stickIfOpen ? dataRef.current.openEvent.type === 'click' : true)) {\n onOpenChange(false, event.nativeEvent, 'click');\n } else {\n onOpenChange(true, event.nativeEvent, 'click');\n }\n },\n onKeyDown(event) {\n pointerTypeRef.current = undefined;\n if (event.defaultPrevented || !keyboardHandlers || isButtonTarget(event)) {\n return;\n }\n if (event.key === ' ' && !isSpaceIgnored(domReference)) {\n // Prevent scrolling\n event.preventDefault();\n didKeyDownRef.current = true;\n }\n if (isAnchorTarget(event)) {\n return;\n }\n if (event.key === 'Enter') {\n if (open && toggle) {\n onOpenChange(false, event.nativeEvent, 'click');\n } else {\n onOpenChange(true, event.nativeEvent, 'click');\n }\n }\n },\n onKeyUp(event) {\n if (event.defaultPrevented || !keyboardHandlers || isButtonTarget(event) || isSpaceIgnored(domReference)) {\n return;\n }\n if (event.key === ' ' && didKeyDownRef.current) {\n didKeyDownRef.current = false;\n if (open && toggle) {\n onOpenChange(false, event.nativeEvent, 'click');\n } else {\n onOpenChange(true, event.nativeEvent, 'click');\n }\n }\n }\n }), [dataRef, domReference, eventOption, ignoreMouse, keyboardHandlers, onOpenChange, open, stickIfOpen, toggle]);\n return React.useMemo(() => enabled ? {\n reference\n } : {}, [enabled, reference]);\n}\n\nfunction createVirtualElement(domElement, data) {\n let offsetX = null;\n let offsetY = null;\n let isAutoUpdateEvent = false;\n return {\n contextElement: domElement || undefined,\n getBoundingClientRect() {\n var _data$dataRef$current;\n const domRect = (domElement == null ? void 0 : domElement.getBoundingClientRect()) || {\n width: 0,\n height: 0,\n x: 0,\n y: 0\n };\n const isXAxis = data.axis === 'x' || data.axis === 'both';\n const isYAxis = data.axis === 'y' || data.axis === 'both';\n const canTrackCursorOnAutoUpdate = ['mouseenter', 'mousemove'].includes(((_data$dataRef$current = data.dataRef.current.openEvent) == null ? void 0 : _data$dataRef$current.type) || '') && data.pointerType !== 'touch';\n let width = domRect.width;\n let height = domRect.height;\n let x = domRect.x;\n let y = domRect.y;\n if (offsetX == null && data.x && isXAxis) {\n offsetX = domRect.x - data.x;\n }\n if (offsetY == null && data.y && isYAxis) {\n offsetY = domRect.y - data.y;\n }\n x -= offsetX || 0;\n y -= offsetY || 0;\n width = 0;\n height = 0;\n if (!isAutoUpdateEvent || canTrackCursorOnAutoUpdate) {\n width = data.axis === 'y' ? domRect.width : 0;\n height = data.axis === 'x' ? domRect.height : 0;\n x = isXAxis && data.x != null ? data.x : x;\n y = isYAxis && data.y != null ? data.y : y;\n } else if (isAutoUpdateEvent && !canTrackCursorOnAutoUpdate) {\n height = data.axis === 'x' ? domRect.height : height;\n width = data.axis === 'y' ? domRect.width : width;\n }\n isAutoUpdateEvent = true;\n return {\n width,\n height,\n x,\n y,\n top: y,\n right: x + width,\n bottom: y + height,\n left: x\n };\n }\n };\n}\nfunction isMouseBasedEvent(event) {\n return event != null && event.clientX != null;\n}\n/**\n * Positions the floating element relative to a client point (in the viewport),\n * such as the mouse position. By default, it follows the mouse cursor.\n * @see https://floating-ui.com/docs/useClientPoint\n */\nfunction useClientPoint(context, props) {\n if (props === void 0) {\n props = {};\n }\n const {\n open,\n dataRef,\n elements: {\n floating,\n domReference\n },\n refs\n } = context;\n const {\n enabled = true,\n axis = 'both',\n x = null,\n y = null\n } = props;\n const initialRef = React.useRef(false);\n const cleanupListenerRef = React.useRef(null);\n const [pointerType, setPointerType] = React.useState();\n const [reactive, setReactive] = React.useState([]);\n const setReference = useEffectEvent((x, y) => {\n if (initialRef.current) return;\n\n // Prevent setting if the open event was not a mouse-like one\n // (e.g. focus to open, then hover over the reference element).\n // Only apply if the event exists.\n if (dataRef.current.openEvent && !isMouseBasedEvent(dataRef.current.openEvent)) {\n return;\n }\n refs.setPositionReference(createVirtualElement(domReference, {\n x,\n y,\n axis,\n dataRef,\n pointerType\n }));\n });\n const handleReferenceEnterOrMove = useEffectEvent(event => {\n if (x != null || y != null) return;\n if (!open) {\n setReference(event.clientX, event.clientY);\n } else if (!cleanupListenerRef.current) {\n // If there's no cleanup, there's no listener, but we want to ensure\n // we add the listener if the cursor landed on the floating element and\n // then back on the reference (i.e. it's interactive).\n setReactive([]);\n }\n });\n\n // If the pointer is a mouse-like pointer, we want to continue following the\n // mouse even if the floating element is transitioning out. On touch\n // devices, this is undesirable because the floating element will move to\n // the dismissal touch point.\n const openCheck = isMouseLikePointerType(pointerType) ? floating : open;\n const addListener = React.useCallback(() => {\n // Explicitly specified `x`/`y` coordinates shouldn't add a listener.\n if (!openCheck || !enabled || x != null || y != null) return;\n const win = getWindow(floating);\n function handleMouseMove(event) {\n const target = getTarget$1(event);\n if (!contains$1(floating, target)) {\n setReference(event.clientX, event.clientY);\n } else {\n win.removeEventListener('mousemove', handleMouseMove);\n cleanupListenerRef.current = null;\n }\n }\n if (!dataRef.current.openEvent || isMouseBasedEvent(dataRef.current.openEvent)) {\n win.addEventListener('mousemove', handleMouseMove);\n const cleanup = () => {\n win.removeEventListener('mousemove', handleMouseMove);\n cleanupListenerRef.current = null;\n };\n cleanupListenerRef.current = cleanup;\n return cleanup;\n }\n refs.setPositionReference(domReference);\n }, [openCheck, enabled, x, y, floating, dataRef, refs, domReference, setReference]);\n React.useEffect(() => {\n return addListener();\n }, [addListener, reactive]);\n React.useEffect(() => {\n if (enabled && !floating) {\n initialRef.current = false;\n }\n }, [enabled, floating]);\n React.useEffect(() => {\n if (!enabled && open) {\n initialRef.current = true;\n }\n }, [enabled, open]);\n useModernLayoutEffect(() => {\n if (enabled && (x != null || y != null)) {\n initialRef.current = false;\n setReference(x, y);\n }\n }, [enabled, x, y, setReference]);\n const reference = React.useMemo(() => {\n function setPointerTypeRef(_ref) {\n let {\n pointerType\n } = _ref;\n setPointerType(pointerType);\n }\n return {\n onPointerDown: setPointerTypeRef,\n onPointerEnter: setPointerTypeRef,\n onMouseMove: handleReferenceEnterOrMove,\n onMouseEnter: handleReferenceEnterOrMove\n };\n }, [handleReferenceEnterOrMove]);\n return React.useMemo(() => enabled ? {\n reference\n } : {}, [enabled, reference]);\n}\n\nconst bubbleHandlerKeys = {\n pointerdown: 'onPointerDown',\n mousedown: 'onMouseDown',\n click: 'onClick'\n};\nconst captureHandlerKeys = {\n pointerdown: 'onPointerDownCapture',\n mousedown: 'onMouseDownCapture',\n click: 'onClickCapture'\n};\nconst normalizeProp = normalizable => {\n var _normalizable$escapeK, _normalizable$outside;\n return {\n escapeKey: typeof normalizable === 'boolean' ? normalizable : (_normalizable$escapeK = normalizable == null ? void 0 : normalizable.escapeKey) != null ? _normalizable$escapeK : false,\n outsidePress: typeof normalizable === 'boolean' ? normalizable : (_normalizable$outside = normalizable == null ? void 0 : normalizable.outsidePress) != null ? _normalizable$outside : true\n };\n};\n/**\n * Closes the floating element when a dismissal is requested — by default, when\n * the user presses the `escape` key or outside of the floating element.\n * @see https://floating-ui.com/docs/useDismiss\n */\nfunction useDismiss(context, props) {\n if (props === void 0) {\n props = {};\n }\n const {\n open,\n onOpenChange,\n elements,\n dataRef\n } = context;\n const {\n enabled = true,\n escapeKey = true,\n outsidePress: unstable_outsidePress = true,\n outsidePressEvent = 'pointerdown',\n referencePress = false,\n referencePressEvent = 'pointerdown',\n ancestorScroll = false,\n bubbles,\n capture\n } = props;\n const tree = useFloatingTree();\n const outsidePressFn = useEffectEvent(typeof unstable_outsidePress === 'function' ? unstable_outsidePress : () => false);\n const outsidePress = typeof unstable_outsidePress === 'function' ? outsidePressFn : unstable_outsidePress;\n const endedOrStartedInsideRef = React.useRef(false);\n const {\n escapeKey: escapeKeyBubbles,\n outsidePress: outsidePressBubbles\n } = normalizeProp(bubbles);\n const {\n escapeKey: escapeKeyCapture,\n outsidePress: outsidePressCapture\n } = normalizeProp(capture);\n const isComposingRef = React.useRef(false);\n const closeOnEscapeKeyDown = useEffectEvent(event => {\n var _dataRef$current$floa;\n if (!open || !enabled || !escapeKey || event.key !== 'Escape') {\n return;\n }\n\n // Wait until IME is settled. Pressing `Escape` while composing should\n // close the compose menu, but not the floating element.\n if (isComposingRef.current) {\n return;\n }\n const nodeId = (_dataRef$current$floa = dataRef.current.floatingContext) == null ? void 0 : _dataRef$current$floa.nodeId;\n const children = tree ? getNodeChildren$1(tree.nodesRef.current, nodeId) : [];\n if (!escapeKeyBubbles) {\n event.stopPropagation();\n if (children.length > 0) {\n let shouldDismiss = true;\n children.forEach(child => {\n var _child$context;\n if ((_child$context = child.context) != null && _child$context.open && !child.context.dataRef.current.__escapeKeyBubbles) {\n shouldDismiss = false;\n return;\n }\n });\n if (!shouldDismiss) {\n return;\n }\n }\n }\n onOpenChange(false, isReactEvent(event) ? event.nativeEvent : event, 'escape-key');\n });\n const closeOnEscapeKeyDownCapture = useEffectEvent(event => {\n var _getTarget2;\n const callback = () => {\n var _getTarget;\n closeOnEscapeKeyDown(event);\n (_getTarget = getTarget$1(event)) == null || _getTarget.removeEventListener('keydown', callback);\n };\n (_getTarget2 = getTarget$1(event)) == null || _getTarget2.addEventListener('keydown', callback);\n });\n const closeOnPressOutside = useEffectEvent(event => {\n var _dataRef$current$floa2;\n // Given developers can stop the propagation of the synthetic event,\n // we can only be confident with a positive value.\n const insideReactTree = dataRef.current.insideReactTree;\n dataRef.current.insideReactTree = false;\n\n // When click outside is lazy (`click` event), handle dragging.\n // Don't close if:\n // - The click started inside the floating element.\n // - The click ended inside the floating element.\n const endedOrStartedInside = endedOrStartedInsideRef.current;\n endedOrStartedInsideRef.current = false;\n if (outsidePressEvent === 'click' && endedOrStartedInside) {\n return;\n }\n if (insideReactTree) {\n return;\n }\n if (typeof outsidePress === 'function' && !outsidePress(event)) {\n return;\n }\n const target = getTarget$1(event);\n const inertSelector = \"[\" + createAttribute('inert') + \"]\";\n const markers = getDocument$1(elements.floating).querySelectorAll(inertSelector);\n let targetRootAncestor = isElement(target) ? target : null;\n while (targetRootAncestor && !isLastTraversableNode(targetRootAncestor)) {\n const nextParent = getParentNode(targetRootAncestor);\n if (isLastTraversableNode(nextParent) || !isElement(nextParent)) {\n break;\n }\n targetRootAncestor = nextParent;\n }\n\n // Check if the click occurred on a third-party element injected after the\n // floating element rendered.\n if (markers.length && isElement(target) && !isRootElement(target) &&\n // Clicked on a direct ancestor (e.g. FloatingOverlay).\n !contains$1(target, elements.floating) &&\n // If the target root element contains none of the markers, then the\n // element was injected after the floating element rendered.\n Array.from(markers).every(marker => !contains$1(targetRootAncestor, marker))) {\n return;\n }\n\n // Check if the click occurred on the scrollbar\n if (isHTMLElement(target) && floating) {\n const lastTraversableNode = isLastTraversableNode(target);\n const style = getComputedStyle(target);\n const scrollRe = /auto|scroll/;\n const isScrollableX = lastTraversableNode || scrollRe.test(style.overflowX);\n const isScrollableY = lastTraversableNode || scrollRe.test(style.overflowY);\n const canScrollX = isScrollableX && target.clientWidth > 0 && target.scrollWidth > target.clientWidth;\n const canScrollY = isScrollableY && target.clientHeight > 0 && target.scrollHeight > target.clientHeight;\n const isRTL = style.direction === 'rtl';\n\n // Check click position relative to scrollbar.\n // In some browsers it is possible to change the <body> (or window)\n // scrollbar to the left side, but is very rare and is difficult to\n // check for. Plus, for modal dialogs with backdrops, it is more\n // important that the backdrop is checked but not so much the window.\n const pressedVerticalScrollbar = canScrollY && (isRTL ? event.offsetX <= target.offsetWidth - target.clientWidth : event.offsetX > target.clientWidth);\n const pressedHorizontalScrollbar = canScrollX && event.offsetY > target.clientHeight;\n if (pressedVerticalScrollbar || pressedHorizontalScrollbar) {\n return;\n }\n }\n const nodeId = (_dataRef$current$floa2 = dataRef.current.floatingContext) == null ? void 0 : _dataRef$current$floa2.nodeId;\n const targetIsInsideChildren = tree && getNodeChildren$1(tree.nodesRef.current, nodeId).some(node => {\n var _node$context;\n return isEventTargetWithin(event, (_node$context = node.context) == null ? void 0 : _node$context.elements.floating);\n });\n if (isEventTargetWithin(event, elements.floating) || isEventTargetWithin(event, elements.domReference) || targetIsInsideChildren) {\n return;\n }\n const children = tree ? getNodeChildren$1(tree.nodesRef.current, nodeId) : [];\n if (children.length > 0) {\n let shouldDismiss = true;\n children.forEach(child => {\n var _child$context2;\n if ((_child$context2 = child.context) != null && _child$context2.open && !child.context.dataRef.current.__outsidePressBubbles) {\n shouldDismiss = false;\n return;\n }\n });\n if (!shouldDismiss) {\n return;\n }\n }\n onOpenChange(false, event, 'outside-press');\n });\n const closeOnPressOutsideCapture = useEffectEvent(event => {\n var _getTarget4;\n const callback = () => {\n var _getTarget3;\n closeOnPressOutside(event);\n (_getTarget3 = getTarget$1(event)) == null || _getTarget3.removeEventListener(outsidePressEvent, callback);\n };\n (_getTarget4 = getTarget$1(event)) == null || _getTarget4.addEventListener(outsidePressEvent, callback);\n });\n React.useEffect(() => {\n if (!open || !enabled) {\n return;\n }\n dataRef.current.__escapeKeyBubbles = escapeKeyBubbles;\n dataRef.current.__outsidePressBubbles = outsidePressBubbles;\n let compositionTimeout = -1;\n function onScroll(event) {\n onOpenChange(false, event, 'ancestor-scroll');\n }\n function handleCompositionStart() {\n window.clearTimeout(compositionTimeout);\n isComposingRef.current = true;\n }\n function handleCompositionEnd() {\n // Safari fires `compositionend` before `keydown`, so we need to wait\n // until the next tick to set `isComposing` to `false`.\n // https://bugs.webkit.org/show_bug.cgi?id=165004\n compositionTimeout = window.setTimeout(() => {\n isComposingRef.current = false;\n },\n // 0ms or 1ms don't work in Safari. 5ms appears to consistently work.\n // Only apply to WebKit for the test to remain 0ms.\n isWebKit() ? 5 : 0);\n }\n const doc = getDocument$1(elements.floating);\n if (escapeKey) {\n doc.addEventListener('keydown', escapeKeyCapture ? closeOnEscapeKeyDownCapture : closeOnEscapeKeyDown, escapeKeyCapture);\n doc.addEventListener('compositionstart', handleCompositionStart);\n doc.addEventListener('compositionend', handleCompositionEnd);\n }\n outsidePress && doc.addEventListener(outsidePressEvent, outsidePressCapture ? closeOnPressOutsideCapture : closeOnPressOutside, outsidePressCapture);\n let ancestors = [];\n if (ancestorScroll) {\n if (isElement(elements.domReference)) {\n ancestors = getOverflowAncestors(elements.domReference);\n }\n if (isElement(elements.floating)) {\n ancestors = ancestors.concat(getOverflowAncestors(elements.floating));\n }\n if (!isElement(elements.reference) && elements.reference && elements.reference.contextElement) {\n ancestors = ancestors.concat(getOverflowAncestors(elements.reference.contextElement));\n }\n }\n\n // Ignore the visual viewport for scrolling dismissal (allow pinch-zoom)\n ancestors = ancestors.filter(ancestor => {\n var _doc$defaultView;\n return ancestor !== ((_doc$defaultView = doc.defaultView) == null ? void 0 : _doc$defaultView.visualViewport);\n });\n ancestors.forEach(ancestor => {\n ancestor.addEventListener('scroll', onScroll);\n });\n return () => {\n if (escapeKey) {\n doc.removeEventListener('keydown', escapeKeyCapture ? closeOnEscapeKeyDownCapture : closeOnEscapeKeyDown, escapeKeyCapture);\n doc.removeEventListener('compositionstart', handleCompositionStart);\n doc.removeEventListener('compositionend', handleCompositionEnd);\n }\n outsidePress && doc.removeEventListener(outsidePressEvent, outsidePressCapture ? closeOnPressOutsideCapture : closeOnPressOutside, outsidePressCapture);\n ancestors.forEach(ancestor => {\n ancestor.removeEventListener('scroll', onScroll);\n });\n window.clearTimeout(compositionTimeout);\n };\n }, [dataRef, elements, escapeKey, outsidePress, outsidePressEvent, open, onOpenChange, ancestorScroll, enabled, escapeKeyBubbles, outsidePressBubbles, closeOnEscapeKeyDown, escapeKeyCapture, closeOnEscapeKeyDownCapture, closeOnPressOutside, outsidePressCapture, closeOnPressOutsideCapture]);\n React.useEffect(() => {\n dataRef.current.insideReactTree = false;\n }, [dataRef, outsidePress, outsidePressEvent]);\n const reference = React.useMemo(() => ({\n onKeyDown: closeOnEscapeKeyDown,\n ...(referencePress && {\n [bubbleHandlerKeys[referencePressEvent]]: event => {\n onOpenChange(false, event.nativeEvent, 'reference-press');\n },\n ...(referencePressEvent !== 'click' && {\n onClick(event) {\n onOpenChange(false, event.nativeEvent, 'reference-press');\n }\n })\n })\n }), [closeOnEscapeKeyDown, onOpenChange, referencePress, referencePressEvent]);\n const floating = React.useMemo(() => {\n function setMouseDownOrUpInside(event) {\n if (event.button !== 0) {\n return;\n }\n endedOrStartedInsideRef.current = true;\n }\n return {\n onKeyDown: closeOnEscapeKeyDown,\n onMouseDown: setMouseDownOrUpInside,\n onMouseUp: setMouseDownOrUpInside,\n [captureHandlerKeys[outsidePressEvent]]: () => {\n dataRef.current.insideReactTree = true;\n }\n };\n }, [closeOnEscapeKeyDown, outsidePressEvent, dataRef]);\n return React.useMemo(() => enabled ? {\n reference,\n floating\n } : {}, [enabled, reference, floating]);\n}\n\nfunction useFloatingRootContext(options) {\n const {\n open = false,\n onOpenChange: onOpenChangeProp,\n elements: elementsProp\n } = options;\n const floatingId = useId();\n const dataRef = React.useRef({});\n const [events] = React.useState(() => createEventEmitter());\n const nested = useFloatingParentNodeId() != null;\n if (process.env.NODE_ENV !== \"production\") {\n const optionDomReference = elementsProp.reference;\n if (optionDomReference && !isElement(optionDomReference)) {\n error('Cannot pass a virtual element to the `elements.reference` option,', 'as it must be a real DOM element. Use `refs.setPositionReference()`', 'instead.');\n }\n }\n const [positionReference, setPositionReference] = React.useState(elementsProp.reference);\n const onOpenChange = useEffectEvent((open, event, reason) => {\n dataRef.current.openEvent = open ? event : undefined;\n events.emit('openchange', {\n open,\n event,\n reason,\n nested\n });\n onOpenChangeProp == null || onOpenChangeProp(open, event, reason);\n });\n const refs = React.useMemo(() => ({\n setPositionReference\n }), []);\n const elements = React.useMemo(() => ({\n reference: positionReference || elementsProp.reference || null,\n floating: elementsProp.floating || null,\n domReference: elementsProp.reference\n }), [positionReference, elementsProp.reference, elementsProp.floating]);\n return React.useMemo(() => ({\n dataRef,\n open,\n onOpenChange,\n elements,\n events,\n floatingId,\n refs\n }), [open, onOpenChange, elements, events, floatingId, refs]);\n}\n\n/**\n * Provides data to position a floating element and context to add interactions.\n * @see https://floating-ui.com/docs/useFloating\n */\nfunction useFloating(_temp) {\n var _elementsOption$refer, _elementsOption$float;\n let {\n elements: elementsOption,\n ...options\n } = _temp === void 0 ? {} : _temp;\n const {\n nodeId\n } = options;\n const internalRootContext = useFloatingRootContext({\n ...options,\n elements: {\n reference: (_elementsOption$refer = elementsOption == null ? void 0 : elementsOption.reference) != null ? _elementsOption$refer : null,\n floating: (_elementsOption$float = elementsOption == null ? void 0 : elementsOption.floating) != null ? _elementsOption$float : null\n }\n });\n const rootContext = options.rootContext || internalRootContext;\n const computedElements = rootContext.elements;\n const [_domReference, setDomReference] = React.useState(null);\n const [positionReference, _setPositionReference] = React.useState(null);\n const optionDomReference = computedElements == null ? void 0 : computedElements.domReference;\n const domReference = optionDomReference || _domReference;\n const domReferenceRef = React.useRef(null);\n const tree = useFloatingTree();\n useModernLayoutEffect(() => {\n if (domReference) {\n domReferenceRef.current = domReference;\n }\n }, [domReference]);\n const position = useFloating$1({\n ...options,\n elements: {\n ...computedElements,\n ...(positionReference && {\n reference: positionReference\n })\n }\n });\n const setPositionReference = React.useCallback(node => {\n const computedPositionReference = isElement(node) ? {\n getBoundingClientRect: () => node.getBoundingClientRect(),\n getClientRects: () => node.getClientRects(),\n contextElement: node\n } : node;\n // Store the positionReference in state if the DOM reference is specified externally via the\n // `elements.reference` option. This ensures that it won't be overridden on future renders.\n _setPositionReference(computedPositionReference);\n position.refs.setReference(computedPositionReference);\n }, [position.refs]);\n const setReference = React.useCallback(node => {\n if (isElement(node) || node === null) {\n domReferenceRef.current = node;\n setDomReference(node);\n }\n\n // Backwards-compatibility for passing a virtual element to `reference`\n // after it has set the DOM reference.\n if (isElement(position.refs.reference.current) || position.refs.reference.current === null ||\n // Don't allow setting virtual elements using the old technique back to\n // `null` to support `positionReference` + an unstable `reference`\n // callback ref.\n node !== null && !isElement(node)) {\n position.refs.setReference(node);\n }\n }, [position.refs]);\n const refs = React.useMemo(() => ({\n ...position.refs,\n setReference,\n setPositionReference,\n domReference: domReferenceRef\n }), [position.refs, setReference, setPositionReference]);\n const elements = React.useMemo(() => ({\n ...position.elements,\n domReference: domReference\n }), [position.elements, domReference]);\n const context = React.useMemo(() => ({\n ...position,\n ...rootContext,\n refs,\n elements,\n nodeId\n }), [position, refs, elements, nodeId, rootContext]);\n useModernLayoutEffect(() => {\n rootContext.dataRef.current.floatingContext = context;\n const node = tree == null ? void 0 : tree.nodesRef.current.find(node => node.id === nodeId);\n if (node) {\n node.context = context;\n }\n });\n return React.useMemo(() => ({\n ...position,\n context,\n refs,\n elements\n }), [position, refs, elements, context]);\n}\n\nfunction isMacSafari() {\n return isMac() && isSafari();\n}\n/**\n * Opens the floating element while the reference element has focus, like CSS\n * `:focus`.\n * @see https://floating-ui.com/docs/useFocus\n */\nfunction useFocus(context, props) {\n if (props === void 0) {\n props = {};\n }\n const {\n open,\n onOpenChange,\n events,\n dataRef,\n elements\n } = context;\n const {\n enabled = true,\n visibleOnly = true\n } = props;\n const blockFocusRef = React.useRef(false);\n const timeoutRef = React.useRef(-1);\n const keyboardModalityRef = React.useRef(true);\n React.useEffect(() => {\n if (!enabled) return;\n const win = getWindow(elements.domReference);\n\n // If the reference was focused and the user left the tab/window, and the\n // floating element was not open, the focus should be blocked when they\n // return to the tab/window.\n function onBlur() {\n if (!open && isHTMLElement(elements.domReference) && elements.domReference === activeElement(getDocument$1(elements.domReference))) {\n blockFocusRef.current = true;\n }\n }\n function onKeyDown() {\n keyboardModalityRef.current = true;\n }\n function onPointerDown() {\n keyboardModalityRef.current = false;\n }\n win.addEventListener('blur', onBlur);\n if (isMacSafari()) {\n win.addEventListener('keydown', onKeyDown, true);\n win.addEventListener('pointerdown', onPointerDown, true);\n }\n return () => {\n win.removeEventListener('blur', onBlur);\n if (isMacSafari()) {\n win.removeEventListener('keydown', onKeyDown, true);\n win.removeEventListener('pointerdown', onPointerDown, true);\n }\n };\n }, [elements.domReference, open, enabled]);\n React.useEffect(() => {\n if (!enabled) return;\n function onOpenChange(_ref) {\n let {\n reason\n } = _ref;\n if (reason === 'reference-press' || reason === 'escape-key') {\n blockFocusRef.current = true;\n }\n }\n events.on('openchange', onOpenChange);\n return () => {\n events.off('openchange', onOpenChange);\n };\n }, [events, enabled]);\n React.useEffect(() => {\n return () => {\n clearTimeoutIfSet(timeoutRef);\n };\n }, []);\n const reference = React.useMemo(() => ({\n onMouseLeave() {\n blockFocusRef.current = false;\n },\n onFocus(event) {\n if (blockFocusRef.current) return;\n const target = getTarget$1(event.nativeEvent);\n if (visibleOnly && isElement(target)) {\n // Safari fails to match `:focus-visible` if focus was initially\n // outside the document.\n if (isMacSafari() && !event.relatedTarget) {\n if (!keyboardModalityRef.current && !isTypeableElement(target)) {\n return;\n }\n } else if (!matchesFocusVisible(target)) {\n return;\n }\n }\n onOpenChange(true, event.nativeEvent, 'focus');\n },\n onBlur(event) {\n blockFocusRef.current = false;\n const relatedTarget = event.relatedTarget;\n const nativeEvent = event.nativeEvent;\n\n // Hit the non-modal focus management portal guard. Focus will be\n // moved into the floating element immediately after.\n const movedToFocusGuard = isElement(relatedTarget) && relatedTarget.hasAttribute(createAttribute('focus-guard')) && relatedTarget.getAttribute('data-type') === 'outside';\n\n // Wait for the window blur listener to fire.\n timeoutRef.current = window.setTimeout(() => {\n var _dataRef$current$floa;\n const activeEl = activeElement(elements.domReference ? elements.domReference.ownerDocument : document);\n\n // Focus left the page, keep it open.\n if (!relatedTarget && activeEl === elements.domReference) return;\n\n // When focusing the reference element (e.g. regular click), then\n // clicking into the floating element, prevent it from hiding.\n // Note: it must be focusable, e.g. `tabindex=\"-1\"`.\n // We can not rely on relatedTarget to point to the correct element\n // as it will only point to the shadow host of the newly focused element\n // and not the element that actually has received focus if it is located\n // inside a shadow root.\n if (contains$1((_dataRef$current$floa = dataRef.current.floatingContext) == null ? void 0 : _dataRef$current$floa.refs.floating.current, activeEl) || contains$1(elements.domReference, activeEl) || movedToFocusGuard) {\n return;\n }\n onOpenChange(false, nativeEvent, 'focus');\n });\n }\n }), [dataRef, elements.domReference, onOpenChange, visibleOnly]);\n return React.useMemo(() => enabled ? {\n reference\n } : {}, [enabled, reference]);\n}\n\nfunction mergeProps(userProps, propsList, elementKey) {\n const map = new Map();\n const isItem = elementKey === 'item';\n let domUserProps = userProps;\n if (isItem && userProps) {\n const {\n [ACTIVE_KEY]: _,\n [SELECTED_KEY]: __,\n ...validProps\n } = userProps;\n domUserProps = validProps;\n }\n return {\n ...(elementKey === 'floating' && {\n tabIndex: -1,\n [FOCUSABLE_ATTRIBUTE]: ''\n }),\n ...domUserProps,\n ...propsList.map(value => {\n const propsOrGetProps = value ? value[elementKey] : null;\n if (typeof propsOrGetProps === 'function') {\n return userProps ? propsOrGetProps(userProps) : null;\n }\n return propsOrGetProps;\n }).concat(userProps).reduce((acc, props) => {\n if (!props) {\n return acc;\n }\n Object.entries(props).forEach(_ref => {\n let [key, value] = _ref;\n if (isItem && [ACTIVE_KEY, SELECTED_KEY].includes(key)) {\n return;\n }\n if (key.indexOf('on') === 0) {\n if (!map.has(key)) {\n map.set(key, []);\n }\n if (typeof value === 'function') {\n var _map$get;\n (_map$get = map.get(key)) == null || _map$get.push(value);\n acc[key] = function () {\n var _map$get2;\n for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {\n args[_key] = arguments[_key];\n }\n return (_map$get2 = map.get(key)) == null ? void 0 : _map$get2.map(fn => fn(...args)).find(val => val !== undefined);\n };\n }\n } else {\n acc[key] = value;\n }\n });\n return acc;\n }, {})\n };\n}\n/**\n * Merges an array of interaction hooks' props into prop getters, allowing\n * event handler functions to be composed together without overwriting one\n * another.\n * @see https://floating-ui.com/docs/useInteractions\n */\nfunction useInteractions(propsList) {\n if (propsList === void 0) {\n propsList = [];\n }\n const referenceDeps = propsList.map(key => key == null ? void 0 : key.reference);\n const floatingDeps = propsList.map(key => key == null ? void 0 : key.floating);\n const itemDeps = propsList.map(key => key == null ? void 0 : key.item);\n const getReferenceProps = React.useCallback(userProps => mergeProps(userProps, propsList, 'reference'),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n referenceDeps);\n const getFloatingProps = React.useCallback(userProps => mergeProps(userProps, propsList, 'floating'),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n floatingDeps);\n const getItemProps = React.useCallback(userProps => mergeProps(userProps, propsList, 'item'),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n itemDeps);\n return React.useMemo(() => ({\n getReferenceProps,\n getFloatingProps,\n getItemProps\n }), [getReferenceProps, getFloatingProps, getItemProps]);\n}\n\nconst ESCAPE = 'Escape';\nfunction doSwitch(orientation, vertical, horizontal) {\n switch (orientation) {\n case 'vertical':\n return vertical;\n case 'horizontal':\n return horizontal;\n default:\n return vertical || horizontal;\n }\n}\nfunction isMainOrientationKey(key, orientation) {\n const vertical = key === ARROW_UP || key === ARROW_DOWN;\n const horizontal = key === ARROW_LEFT || key === ARROW_RIGHT;\n return doSwitch(orientation, vertical, horizontal);\n}\nfunction isMainOrientationToEndKey(key, orientation, rtl) {\n const vertical = key === ARROW_DOWN;\n const horizontal = rtl ? key === ARROW_LEFT : key === ARROW_RIGHT;\n return doSwitch(orientation, vertical, horizontal) || key === 'Enter' || key === ' ' || key === '';\n}\nfunction isCrossOrientationOpenKey(key, orientation, rtl) {\n const vertical = rtl ? key === ARROW_LEFT : key === ARROW_RIGHT;\n const horizontal = key === ARROW_DOWN;\n return doSwitch(orientation, vertical, horizontal);\n}\nfunction isCrossOrientationCloseKey(key, orientation, rtl, cols) {\n const vertical = rtl ? key === ARROW_RIGHT : key === ARROW_LEFT;\n const horizontal = key === ARROW_UP;\n if (orientation === 'both' || orientation === 'horizontal' && cols && cols > 1) {\n return key === ESCAPE;\n }\n return doSwitch(orientation, vertical, horizontal);\n}\n/**\n * Adds arrow key-based navigation of a list of items, either using real DOM\n * focus or virtual focus.\n * @see https://floating-ui.com/docs/useListNavigation\n */\nfunction useListNavigation(context, props) {\n const {\n open,\n onOpenChange,\n elements,\n floatingId\n } = context;\n const {\n listRef,\n activeIndex,\n onNavigate: unstable_onNavigate = () => {},\n enabled = true,\n selectedIndex = null,\n allowEscape = false,\n loop = false,\n nested = false,\n rtl = false,\n virtual = false,\n focusItemOnOpen = 'auto',\n focusItemOnHover = true,\n openOnArrowKeyDown = true,\n disabledIndices = undefined,\n orientation = 'vertical',\n parentOrientation,\n cols = 1,\n scrollItemIntoView = true,\n virtualItemRef,\n itemSizes,\n dense = false\n } = props;\n if (process.env.NODE_ENV !== \"production\") {\n if (allowEscape) {\n if (!loop) {\n warn('`useListNavigation` looping must be enabled to allow escaping.');\n }\n if (!virtual) {\n warn('`useListNavigation` must be virtual to allow escaping.');\n }\n }\n if (orientation === 'vertical' && cols > 1) {\n warn('In grid list navigation mode (`cols` > 1), the `orientation` should', 'be either \"horizontal\" or \"both\".');\n }\n }\n const floatingFocusElement = getFloatingFocusElement(elements.floating);\n const floatingFocusElementRef = useLatestRef(floatingFocusElement);\n const parentId = useFloatingParentNodeId();\n const tree = useFloatingTree();\n useModernLayoutEffect(() => {\n context.dataRef.current.orientation = orientation;\n }, [context, orientation]);\n const onNavigate = useEffectEvent(() => {\n unstable_onNavigate(indexRef.current === -1 ? null : indexRef.current);\n });\n const typeableComboboxReference = isTypeableCombobox(elements.domReference);\n const focusItemOnOpenRef = React.useRef(focusItemOnOpen);\n const indexRef = React.useRef(selectedIndex != null ? selectedIndex : -1);\n const keyRef = React.useRef(null);\n const isPointerModalityRef = React.useRef(true);\n const previousOnNavigateRef = React.useRef(onNavigate);\n const previousMountedRef = React.useRef(!!elements.floating);\n const previousOpenRef = React.useRef(open);\n const forceSyncFocusRef = React.useRef(false);\n const forceScrollIntoViewRef = React.useRef(false);\n const disabledIndicesRef = useLatestRef(disabledIndices);\n const latestOpenRef = useLatestRef(open);\n const scrollItemIntoViewRef = useLatestRef(scrollItemIntoView);\n const selectedIndexRef = useLatestRef(selectedIndex);\n const [activeId, setActiveId] = React.useState();\n const [virtualId, setVirtualId] = React.useState();\n const focusItem = useEffectEvent(() => {\n function runFocus(item) {\n if (virtual) {\n var _item$id;\n if ((_item$id = item.id) != null && _item$id.endsWith('-fui-option')) {\n item.id = floatingId + \"-\" + Math.random().toString(16).slice(2, 10);\n }\n setActiveId(item.id);\n tree == null || tree.events.emit('virtualfocus', item);\n if (virtualItemRef) {\n virtualItemRef.current = item;\n }\n } else {\n enqueueFocus(item, {\n sync: forceSyncFocusRef.current,\n preventScroll: true\n });\n }\n }\n const initialItem = listRef.current[indexRef.current];\n const forceScrollIntoView = forceScrollIntoViewRef.current;\n if (initialItem) {\n runFocus(initialItem);\n }\n const scheduler = forceSyncFocusRef.current ? v => v() : requestAnimationFrame;\n scheduler(() => {\n const waitedItem = listRef.current[indexRef.current] || initialItem;\n if (!waitedItem) return;\n if (!initialItem) {\n runFocus(waitedItem);\n }\n const scrollIntoViewOptions = scrollItemIntoViewRef.current;\n const shouldScrollIntoView = scrollIntoViewOptions && item && (forceScrollIntoView || !isPointerModalityRef.current);\n if (shouldScrollIntoView) {\n // JSDOM doesn't support `.scrollIntoView()` but it's widely supported\n // by all browsers.\n waitedItem.scrollIntoView == null || waitedItem.scrollIntoView(typeof scrollIntoViewOptions === 'boolean' ? {\n block: 'nearest',\n inline: 'nearest'\n } : scrollIntoViewOptions);\n }\n });\n });\n\n // Sync `selectedIndex` to be the `activeIndex` upon opening the floating\n // element. Also, reset `activeIndex` upon closing the floating element.\n useModernLayoutEffect(() => {\n if (!enabled) return;\n if (open && elements.floating) {\n if (focusItemOnOpenRef.current && selectedIndex != null) {\n // Regardless of the pointer modality, we want to ensure the selected\n // item comes into view when the floating element is opened.\n forceScrollIntoViewRef.current = true;\n indexRef.current = selectedIndex;\n onNavigate();\n }\n } else if (previousMountedRef.current) {\n // Since the user can specify `onNavigate` conditionally\n // (onNavigate: open ? setActiveIndex : setSelectedIndex),\n // we store and call the previous function.\n indexRef.current = -1;\n previousOnNavigateRef.current();\n }\n }, [enabled, open, elements.floating, selectedIndex, onNavigate]);\n\n // Sync `activeIndex` to be the focused item while the floating element is\n // open.\n useModernLayoutEffect(() => {\n if (!enabled) return;\n if (!open) return;\n if (!elements.floating) return;\n if (activeIndex == null) {\n forceSyncFocusRef.current = false;\n if (selectedIndexRef.current != null) {\n return;\n }\n\n // Reset while the floating element was open (e.g. the list changed).\n if (previousMountedRef.current) {\n indexRef.current = -1;\n focusItem();\n }\n\n // Initial sync.\n if ((!previousOpenRef.current || !previousMountedRef.current) && focusItemOnOpenRef.current && (keyRef.current != null || focusItemOnOpenRef.current === true && keyRef.current == null)) {\n let runs = 0;\n const waitForListPopulated = () => {\n if (listRef.current[0] == null) {\n // Avoid letting the browser paint if possible on the first try,\n // otherwise use rAF. Don't try more than twice, since something\n // is wrong otherwise.\n if (runs < 2) {\n const scheduler = runs ? requestAnimationFrame : queueMicrotask;\n scheduler(waitForListPopulated);\n }\n runs++;\n } else {\n indexRef.current = keyRef.current == null || isMainOrientationToEndKey(keyRef.current, orientation, rtl) || nested ? getMinListIndex(listRef, disabledIndicesRef.current) : getMaxListIndex(listRef, disabledIndicesRef.current);\n keyRef.current = null;\n onNavigate();\n }\n };\n waitForListPopulated();\n }\n } else if (!isIndexOutOfListBounds(listRef, activeIndex)) {\n indexRef.current = activeIndex;\n focusItem();\n forceScrollIntoViewRef.current = false;\n }\n }, [enabled, open, elements.floating, activeIndex, selectedIndexRef, nested, listRef, orientation, rtl, onNavigate, focusItem, disabledIndicesRef]);\n\n // Ensure the parent floating element has focus when a nested child closes\n // to allow arrow key navigation to work after the pointer leaves the child.\n useModernLayoutEffect(() => {\n var _nodes$find;\n if (!enabled || elements.floating || !tree || virtual || !previousMountedRef.current) {\n return;\n }\n const nodes = tree.nodesRef.current;\n const parent = (_nodes$find = nodes.find(node => node.id === parentId)) == null || (_nodes$find = _nodes$find.context) == null ? void 0 : _nodes$find.elements.floating;\n const activeEl = activeElement(getDocument$1(elements.floating));\n const treeContainsActiveEl = nodes.some(node => node.context && contains$1(node.context.elements.floating, activeEl));\n if (parent && !treeContainsActiveEl && isPointerModalityRef.current) {\n parent.focus({\n preventScroll: true\n });\n }\n }, [enabled, elements.floating, tree, parentId, virtual]);\n useModernLayoutEffect(() => {\n if (!enabled) return;\n if (!tree) return;\n if (!virtual) return;\n if (parentId) return;\n function handleVirtualFocus(item) {\n setVirtualId(item.id);\n if (virtualItemRef) {\n virtualItemRef.current = item;\n }\n }\n tree.events.on('virtualfocus', handleVirtualFocus);\n return () => {\n tree.events.off('virtualfocus', handleVirtualFocus);\n };\n }, [enabled, tree, virtual, parentId, virtualItemRef]);\n useModernLayoutEffect(() => {\n previousOnNavigateRef.current = onNavigate;\n previousOpenRef.current = open;\n previousMountedRef.current = !!elements.floating;\n });\n useModernLayoutEffect(() => {\n if (!open) {\n keyRef.current = null;\n focusItemOnOpenRef.current = focusItemOnOpen;\n }\n }, [open, focusItemOnOpen]);\n const hasActiveIndex = activeIndex != null;\n const item = React.useMemo(() => {\n function syncCurrentTarget(currentTarget) {\n if (!latestOpenRef.current) return;\n const index = listRef.current.indexOf(currentTarget);\n if (index !== -1 && indexRef.current !== index) {\n indexRef.current = index;\n onNavigate();\n }\n }\n const props = {\n onFocus(_ref) {\n let {\n currentTarget\n } = _ref;\n forceSyncFocusRef.current = true;\n syncCurrentTarget(currentTarget);\n },\n onClick: _ref2 => {\n let {\n currentTarget\n } = _ref2;\n return currentTarget.focus({\n preventScroll: true\n });\n },\n // Safari\n onMouseMove(_ref3) {\n let {\n currentTarget\n } = _ref3;\n forceSyncFocusRef.current = true;\n forceScrollIntoViewRef.current = false;\n if (focusItemOnHover) {\n syncCurrentTarget(currentTarget);\n }\n },\n onPointerLeave(_ref4) {\n let {\n pointerType\n } = _ref4;\n if (!isPointerModalityRef.current || pointerType === 'touch') {\n return;\n }\n forceSyncFocusRef.current = true;\n if (!focusItemOnHover) {\n return;\n }\n indexRef.current = -1;\n onNavigate();\n if (!virtual) {\n var _floatingFocusElement;\n (_floatingFocusElement = floatingFocusElementRef.current) == null || _floatingFocusElement.focus({\n preventScroll: true\n });\n }\n }\n };\n return props;\n }, [latestOpenRef, floatingFocusElementRef, focusItemOnHover, listRef, onNavigate, virtual]);\n const getParentOrientation = React.useCallback(() => {\n var _tree$nodesRef$curren;\n return parentOrientation != null ? parentOrientation : tree == null || (_tree$nodesRef$curren = tree.nodesRef.current.find(node => node.id === parentId)) == null || (_tree$nodesRef$curren = _tree$nodesRef$curren.context) == null || (_tree$nodesRef$curren = _tree$nodesRef$curren.dataRef) == null ? void 0 : _tree$nodesRef$curren.current.orientation;\n }, [parentId, tree, parentOrientation]);\n const commonOnKeyDown = useEffectEvent(event => {\n isPointerModalityRef.current = false;\n forceSyncFocusRef.current = true;\n\n // When composing a character, Chrome fires ArrowDown twice. Firefox/Safari\n // don't appear to suffer from this. `event.isComposing` is avoided due to\n // Safari not supporting it properly (although it's not needed in the first\n // place for Safari, just avoiding any possible issues).\n if (event.which === 229) {\n return;\n }\n\n // If the floating element is animating out, ignore navigation. Otherwise,\n // the `activeIndex` gets set to 0 despite not being open so the next time\n // the user ArrowDowns, the first item won't be focused.\n if (!latestOpenRef.current && event.currentTarget === floatingFocusElementRef.current) {\n return;\n }\n if (nested && isCrossOrientationCloseKey(event.key, orientation, rtl, cols)) {\n // If the nested list's close key is also the parent navigation key,\n // let the parent navigate. Otherwise, stop propagating the event.\n if (!isMainOrientationKey(event.key, getParentOrientation())) {\n stopEvent(event);\n }\n onOpenChange(false, event.nativeEvent, 'list-navigation');\n if (isHTMLElement(elements.domReference)) {\n if (virtual) {\n tree == null || tree.events.emit('virtualfocus', elements.domReference);\n } else {\n elements.domReference.focus();\n }\n }\n return;\n }\n const currentIndex = indexRef.current;\n const minIndex = getMinListIndex(listRef, disabledIndices);\n const maxIndex = getMaxListIndex(listRef, disabledIndices);\n if (!typeableComboboxReference) {\n if (event.key === 'Home') {\n stopEvent(event);\n indexRef.current = minIndex;\n onNavigate();\n }\n if (event.key === 'End') {\n stopEvent(event);\n indexRef.current = maxIndex;\n onNavigate();\n }\n }\n\n // Grid navigation.\n if (cols > 1) {\n const sizes = itemSizes || Array.from({\n length: listRef.current.length\n }, () => ({\n width: 1,\n height: 1\n }));\n // To calculate movements on the grid, we use hypothetical cell indices\n // as if every item was 1x1, then convert back to real indices.\n const cellMap = createGridCellMap(sizes, cols, dense);\n const minGridIndex = cellMap.findIndex(index => index != null && !isListIndexDisabled(listRef, index, disabledIndices));\n // last enabled index\n const maxGridIndex = cellMap.reduce((foundIndex, index, cellIndex) => index != null && !isListIndexDisabled(listRef, index, disabledIndices) ? cellIndex : foundIndex, -1);\n const index = cellMap[getGridNavigatedIndex({\n current: cellMap.map(itemIndex => itemIndex != null ? listRef.current[itemIndex] : null)\n }, {\n event,\n orientation,\n loop,\n rtl,\n cols,\n // treat undefined (empty grid spaces) as disabled indices so we\n // don't end up in them\n disabledIndices: getGridCellIndices([...((typeof disabledIndices !== 'function' ? disabledIndices : null) || listRef.current.map((_, index) => isListIndexDisabled(listRef, index, disabledIndices) ? index : undefined)), undefined], cellMap),\n minIndex: minGridIndex,\n maxIndex: maxGridIndex,\n prevIndex: getGridCellIndexOfCorner(indexRef.current > maxIndex ? minIndex : indexRef.current, sizes, cellMap, cols,\n // use a corner matching the edge closest to the direction\n // we're moving in so we don't end up in the same item. Prefer\n // top/left over bottom/right.\n event.key === ARROW_DOWN ? 'bl' : event.key === (rtl ? ARROW_LEFT : ARROW_RIGHT) ? 'tr' : 'tl'),\n stopEvent: true\n })];\n if (index != null) {\n indexRef.current = index;\n onNavigate();\n }\n if (orientation === 'both') {\n return;\n }\n }\n if (isMainOrientationKey(event.key, orientation)) {\n stopEvent(event);\n\n // Reset the index if no item is focused.\n if (open && !virtual && activeElement(event.currentTarget.ownerDocument) === event.currentTarget) {\n indexRef.current = isMainOrientationToEndKey(event.key, orientation, rtl) ? minIndex : maxIndex;\n onNavigate();\n return;\n }\n if (isMainOrientationToEndKey(event.key, orientation, rtl)) {\n if (loop) {\n indexRef.current = currentIndex >= maxIndex ? allowEscape && currentIndex !== listRef.current.length ? -1 : minIndex : findNonDisabledListIndex(listRef, {\n startingIndex: currentIndex,\n disabledIndices\n });\n } else {\n indexRef.current = Math.min(maxIndex, findNonDisabledListIndex(listRef, {\n startingIndex: currentIndex,\n disabledIndices\n }));\n }\n } else {\n if (loop) {\n indexRef.current = currentIndex <= minIndex ? allowEscape && currentIndex !== -1 ? listRef.current.length : maxIndex : findNonDisabledListIndex(listRef, {\n startingIndex: currentIndex,\n decrement: true,\n disabledIndices\n });\n } else {\n indexRef.current = Math.max(minIndex, findNonDisabledListIndex(listRef, {\n startingIndex: currentIndex,\n decrement: true,\n disabledIndices\n }));\n }\n }\n if (isIndexOutOfListBounds(listRef, indexRef.current)) {\n indexRef.current = -1;\n }\n onNavigate();\n }\n });\n const ariaActiveDescendantProp = React.useMemo(() => {\n return virtual && open && hasActiveIndex && {\n 'aria-activedescendant': virtualId || activeId\n };\n }, [virtual, open, hasActiveIndex, virtualId, activeId]);\n const floating = React.useMemo(() => {\n return {\n 'aria-orientation': orientation === 'both' ? undefined : orientation,\n ...(!typeableComboboxReference ? ariaActiveDescendantProp : {}),\n onKeyDown: commonOnKeyDown,\n onPointerMove() {\n isPointerModalityRef.current = true;\n }\n };\n }, [ariaActiveDescendantProp, commonOnKeyDown, orientation, typeableComboboxReference]);\n const reference = React.useMemo(() => {\n function checkVirtualMouse(event) {\n if (focusItemOnOpen === 'auto' && isVirtualClick(event.nativeEvent)) {\n focusItemOnOpenRef.current = true;\n }\n }\n function checkVirtualPointer(event) {\n // `pointerdown` fires first, reset the state then perform the checks.\n focusItemOnOpenRef.current = focusItemOnOpen;\n if (focusItemOnOpen === 'auto' && isVirtualPointerEvent(event.nativeEvent)) {\n focusItemOnOpenRef.current = true;\n }\n }\n return {\n ...ariaActiveDescendantProp,\n onKeyDown(event) {\n isPointerModalityRef.current = false;\n const isArrowKey = event.key.startsWith('Arrow');\n const isHomeOrEndKey = ['Home', 'End'].includes(event.key);\n const isMoveKey = isArrowKey || isHomeOrEndKey;\n const isCrossOpenKey = isCrossOrientationOpenKey(event.key, orientation, rtl);\n const isCrossCloseKey = isCrossOrientationCloseKey(event.key, orientation, rtl, cols);\n const isParentCrossOpenKey = isCrossOrientationOpenKey(event.key, getParentOrientation(), rtl);\n const isMainKey = isMainOrientationKey(event.key, orientation);\n const isNavigationKey = (nested ? isParentCrossOpenKey : isMainKey) || event.key === 'Enter' || event.key.trim() === '';\n if (virtual && open) {\n const rootNode = tree == null ? void 0 : tree.nodesRef.current.find(node => node.parentId == null);\n const deepestNode = tree && rootNode ? getDeepestNode(tree.nodesRef.current, rootNode.id) : null;\n if (isMoveKey && deepestNode && virtualItemRef) {\n const eventObject = new KeyboardEvent('keydown', {\n key: event.key,\n bubbles: true\n });\n if (isCrossOpenKey || isCrossCloseKey) {\n var _deepestNode$context, _deepestNode$context2;\n const isCurrentTarget = ((_deepestNode$context = deepestNode.context) == null ? void 0 : _deepestNode$context.elements.domReference) === event.currentTarget;\n const dispatchItem = isCrossCloseKey && !isCurrentTarget ? (_deepestNode$context2 = deepestNode.context) == null ? void 0 : _deepestNode$context2.elements.domReference : isCrossOpenKey ? listRef.current.find(item => (item == null ? void 0 : item.id) === activeId) : null;\n if (dispatchItem) {\n stopEvent(event);\n dispatchItem.dispatchEvent(eventObject);\n setVirtualId(undefined);\n }\n }\n if ((isMainKey || isHomeOrEndKey) && deepestNode.context) {\n if (deepestNode.context.open && deepestNode.parentId && event.currentTarget !== deepestNode.context.elements.domReference) {\n var _deepestNode$context$;\n stopEvent(event);\n (_deepestNode$context$ = deepestNode.context.elements.domReference) == null || _deepestNode$context$.dispatchEvent(eventObject);\n return;\n }\n }\n }\n return commonOnKeyDown(event);\n }\n // If a floating element should not open on arrow key down, avoid\n // setting `activeIndex` while it's closed.\n if (!open && !openOnArrowKeyDown && isArrowKey) {\n return;\n }\n if (isNavigationKey) {\n const isParentMainKey = isMainOrientationKey(event.key, getParentOrientation());\n keyRef.current = nested && isParentMainKey ? null : event.key;\n }\n if (nested) {\n if (isParentCrossOpenKey) {\n stopEvent(event);\n if (open) {\n indexRef.current = getMinListIndex(listRef, disabledIndicesRef.current);\n onNavigate();\n } else {\n onOpenChange(true, event.nativeEvent, 'list-navigation');\n }\n }\n return;\n }\n if (isMainKey) {\n if (selectedIndex != null) {\n indexRef.current = selectedIndex;\n }\n stopEvent(event);\n if (!open && openOnArrowKeyDown) {\n onOpenChange(true, event.nativeEvent, 'list-navigation');\n } else {\n commonOnKeyDown(event);\n }\n if (open) {\n onNavigate();\n }\n }\n },\n onFocus() {\n if (open && !virtual) {\n indexRef.current = -1;\n onNavigate();\n }\n },\n onPointerDown: checkVirtualPointer,\n onPointerEnter: checkVirtualPointer,\n onMouseDown: checkVirtualMouse,\n onClick: checkVirtualMouse\n };\n }, [activeId, ariaActiveDescendantProp, cols, commonOnKeyDown, disabledIndicesRef, focusItemOnOpen, listRef, nested, onNavigate, onOpenChange, open, openOnArrowKeyDown, orientation, getParentOrientation, rtl, selectedIndex, tree, virtual, virtualItemRef]);\n return React.useMemo(() => enabled ? {\n reference,\n floating,\n item\n } : {}, [enabled, reference, floating, item]);\n}\n\nconst componentRoleToAriaRoleMap = /*#__PURE__*/new Map([['select', 'listbox'], ['combobox', 'listbox'], ['label', false]]);\n\n/**\n * Adds base screen reader props to the reference and floating elements for a\n * given floating element `role`.\n * @see https://floating-ui.com/docs/useRole\n */\nfunction useRole(context, props) {\n var _elements$domReferenc, _componentRoleToAriaR;\n if (props === void 0) {\n props = {};\n }\n const {\n open,\n elements,\n floatingId: defaultFloatingId\n } = context;\n const {\n enabled = true,\n role = 'dialog'\n } = props;\n const defaultReferenceId = useId();\n const referenceId = ((_elements$domReferenc = elements.domReference) == null ? void 0 : _elements$domReferenc.id) || defaultReferenceId;\n const floatingId = React.useMemo(() => {\n var _getFloatingFocusElem;\n return ((_getFloatingFocusElem = getFloatingFocusElement(elements.floating)) == null ? void 0 : _getFloatingFocusElem.id) || defaultFloatingId;\n }, [elements.floating, defaultFloatingId]);\n const ariaRole = (_componentRoleToAriaR = componentRoleToAriaRoleMap.get(role)) != null ? _componentRoleToAriaR : role;\n const parentId = useFloatingParentNodeId();\n const isNested = parentId != null;\n const reference = React.useMemo(() => {\n if (ariaRole === 'tooltip' || role === 'label') {\n return {\n [\"aria-\" + (role === 'label' ? 'labelledby' : 'describedby')]: open ? floatingId : undefined\n };\n }\n return {\n 'aria-expanded': open ? 'true' : 'false',\n 'aria-haspopup': ariaRole === 'alertdialog' ? 'dialog' : ariaRole,\n 'aria-controls': open ? floatingId : undefined,\n ...(ariaRole === 'listbox' && {\n role: 'combobox'\n }),\n ...(ariaRole === 'menu' && {\n id: referenceId\n }),\n ...(ariaRole === 'menu' && isNested && {\n role: 'menuitem'\n }),\n ...(role === 'select' && {\n 'aria-autocomplete': 'none'\n }),\n ...(role === 'combobox' && {\n 'aria-autocomplete': 'list'\n })\n };\n }, [ariaRole, floatingId, isNested, open, referenceId, role]);\n const floating = React.useMemo(() => {\n const floatingProps = {\n id: floatingId,\n ...(ariaRole && {\n role: ariaRole\n })\n };\n if (ariaRole === 'tooltip' || role === 'label') {\n return floatingProps;\n }\n return {\n ...floatingProps,\n ...(ariaRole === 'menu' && {\n 'aria-labelledby': referenceId\n })\n };\n }, [ariaRole, floatingId, referenceId, role]);\n const item = React.useCallback(_ref => {\n let {\n active,\n selected\n } = _ref;\n const commonProps = {\n role: 'option',\n ...(active && {\n id: floatingId + \"-fui-option\"\n })\n };\n\n // For `menu`, we are unable to tell if the item is a `menuitemradio`\n // or `menuitemcheckbox`. For backwards-compatibility reasons, also\n // avoid defaulting to `menuitem` as it may overwrite custom role props.\n switch (role) {\n case 'select':\n case 'combobox':\n return {\n ...commonProps,\n 'aria-selected': selected\n };\n }\n return {};\n }, [floatingId, role]);\n return React.useMemo(() => enabled ? {\n reference,\n floating,\n item\n } : {}, [enabled, reference, floating, item]);\n}\n\n// Converts a JS style key like `backgroundColor` to a CSS transition-property\n// like `background-color`.\nconst camelCaseToKebabCase = str => str.replace(/[A-Z]+(?![a-z])|[A-Z]/g, ($, ofs) => (ofs ? '-' : '') + $.toLowerCase());\nfunction execWithArgsOrReturn(valueOrFn, args) {\n return typeof valueOrFn === 'function' ? valueOrFn(args) : valueOrFn;\n}\nfunction useDelayUnmount(open, durationMs) {\n const [isMounted, setIsMounted] = React.useState(open);\n if (open && !isMounted) {\n setIsMounted(true);\n }\n React.useEffect(() => {\n if (!open && isMounted) {\n const timeout = setTimeout(() => setIsMounted(false), durationMs);\n return () => clearTimeout(timeout);\n }\n }, [open, isMounted, durationMs]);\n return isMounted;\n}\n/**\n * Provides a status string to apply CSS transitions to a floating element,\n * correctly handling placement-aware transitions.\n * @see https://floating-ui.com/docs/useTransition#usetransitionstatus\n */\nfunction useTransitionStatus(context, props) {\n if (props === void 0) {\n props = {};\n }\n const {\n open,\n elements: {\n floating\n }\n } = context;\n const {\n duration = 250\n } = props;\n const isNumberDuration = typeof duration === 'number';\n const closeDuration = (isNumberDuration ? duration : duration.close) || 0;\n const [status, setStatus] = React.useState('unmounted');\n const isMounted = useDelayUnmount(open, closeDuration);\n if (!isMounted && status === 'close') {\n setStatus('unmounted');\n }\n useModernLayoutEffect(() => {\n if (!floating) return;\n if (open) {\n setStatus('initial');\n const frame = requestAnimationFrame(() => {\n // Ensure it opens before paint. With `FloatingDelayGroup`,\n // this avoids a flicker when moving between floating elements\n // to ensure one is always open with no missing frames.\n ReactDOM.flushSync(() => {\n setStatus('open');\n });\n });\n return () => {\n cancelAnimationFrame(frame);\n };\n }\n setStatus('close');\n }, [open, floating]);\n return {\n isMounted,\n status\n };\n}\n/**\n * Provides styles to apply CSS transitions to a floating element, correctly\n * handling placement-aware transitions. Wrapper around `useTransitionStatus`.\n * @see https://floating-ui.com/docs/useTransition#usetransitionstyles\n */\nfunction useTransitionStyles(context, props) {\n if (props === void 0) {\n props = {};\n }\n const {\n initial: unstable_initial = {\n opacity: 0\n },\n open: unstable_open,\n close: unstable_close,\n common: unstable_common,\n duration = 250\n } = props;\n const placement = context.placement;\n const side = placement.split('-')[0];\n const fnArgs = React.useMemo(() => ({\n side,\n placement\n }), [side, placement]);\n const isNumberDuration = typeof duration === 'number';\n const openDuration = (isNumberDuration ? duration : duration.open) || 0;\n const closeDuration = (isNumberDuration ? duration : duration.close) || 0;\n const [styles, setStyles] = React.useState(() => ({\n ...execWithArgsOrReturn(unstable_common, fnArgs),\n ...execWithArgsOrReturn(unstable_initial, fnArgs)\n }));\n const {\n isMounted,\n status\n } = useTransitionStatus(context, {\n duration\n });\n const initialRef = useLatestRef(unstable_initial);\n const openRef = useLatestRef(unstable_open);\n const closeRef = useLatestRef(unstable_close);\n const commonRef = useLatestRef(unstable_common);\n useModernLayoutEffect(() => {\n const initialStyles = execWithArgsOrReturn(initialRef.current, fnArgs);\n const closeStyles = execWithArgsOrReturn(closeRef.current, fnArgs);\n const commonStyles = execWithArgsOrReturn(commonRef.current, fnArgs);\n const openStyles = execWithArgsOrReturn(openRef.current, fnArgs) || Object.keys(initialStyles).reduce((acc, key) => {\n acc[key] = '';\n return acc;\n }, {});\n if (status === 'initial') {\n setStyles(styles => ({\n transitionProperty: styles.transitionProperty,\n ...commonStyles,\n ...initialStyles\n }));\n }\n if (status === 'open') {\n setStyles({\n transitionProperty: Object.keys(openStyles).map(camelCaseToKebabCase).join(','),\n transitionDuration: openDuration + \"ms\",\n ...commonStyles,\n ...openStyles\n });\n }\n if (status === 'close') {\n const styles = closeStyles || initialStyles;\n setStyles({\n transitionProperty: Object.keys(styles).map(camelCaseToKebabCase).join(','),\n transitionDuration: closeDuration + \"ms\",\n ...commonStyles,\n ...styles\n });\n }\n }, [closeDuration, closeRef, initialRef, openRef, commonRef, openDuration, status, fnArgs]);\n return {\n isMounted,\n styles\n };\n}\n\n/**\n * Provides a matching callback that can be used to focus an item as the user\n * types, often used in tandem with `useListNavigation()`.\n * @see https://floating-ui.com/docs/useTypeahead\n */\nfunction useTypeahead(context, props) {\n var _ref;\n const {\n open,\n dataRef\n } = context;\n const {\n listRef,\n activeIndex,\n onMatch: unstable_onMatch,\n onTypingChange: unstable_onTypingChange,\n enabled = true,\n findMatch = null,\n resetMs = 750,\n ignoreKeys = [],\n selectedIndex = null\n } = props;\n const timeoutIdRef = React.useRef(-1);\n const stringRef = React.useRef('');\n const prevIndexRef = React.useRef((_ref = selectedIndex != null ? selectedIndex : activeIndex) != null ? _ref : -1);\n const matchIndexRef = React.useRef(null);\n const onMatch = useEffectEvent(unstable_onMatch);\n const onTypingChange = useEffectEvent(unstable_onTypingChange);\n const findMatchRef = useLatestRef(findMatch);\n const ignoreKeysRef = useLatestRef(ignoreKeys);\n useModernLayoutEffect(() => {\n if (open) {\n clearTimeoutIfSet(timeoutIdRef);\n matchIndexRef.current = null;\n stringRef.current = '';\n }\n }, [open]);\n useModernLayoutEffect(() => {\n // Sync arrow key navigation but not typeahead navigation.\n if (open && stringRef.current === '') {\n var _ref2;\n prevIndexRef.current = (_ref2 = selectedIndex != null ? selectedIndex : activeIndex) != null ? _ref2 : -1;\n }\n }, [open, selectedIndex, activeIndex]);\n const setTypingChange = useEffectEvent(value => {\n if (value) {\n if (!dataRef.current.typing) {\n dataRef.current.typing = value;\n onTypingChange(value);\n }\n } else {\n if (dataRef.current.typing) {\n dataRef.current.typing = value;\n onTypingChange(value);\n }\n }\n });\n const onKeyDown = useEffectEvent(event => {\n function getMatchingIndex(list, orderedList, string) {\n const str = findMatchRef.current ? findMatchRef.current(orderedList, string) : orderedList.find(text => (text == null ? void 0 : text.toLocaleLowerCase().indexOf(string.toLocaleLowerCase())) === 0);\n return str ? list.indexOf(str) : -1;\n }\n const listContent = listRef.current;\n if (stringRef.current.length > 0 && stringRef.current[0] !== ' ') {\n if (getMatchingIndex(listContent, listContent, stringRef.current) === -1) {\n setTypingChange(false);\n } else if (event.key === ' ') {\n stopEvent(event);\n }\n }\n if (listContent == null || ignoreKeysRef.current.includes(event.key) ||\n // Character key.\n event.key.length !== 1 ||\n // Modifier key.\n event.ctrlKey || event.metaKey || event.altKey) {\n return;\n }\n if (open && event.key !== ' ') {\n stopEvent(event);\n setTypingChange(true);\n }\n\n // Bail out if the list contains a word like \"llama\" or \"aaron\". TODO:\n // allow it in this case, too.\n const allowRapidSuccessionOfFirstLetter = listContent.every(text => {\n var _text$, _text$2;\n return text ? ((_text$ = text[0]) == null ? void 0 : _text$.toLocaleLowerCase()) !== ((_text$2 = text[1]) == null ? void 0 : _text$2.toLocaleLowerCase()) : true;\n });\n\n // Allows the user to cycle through items that start with the same letter\n // in rapid succession.\n if (allowRapidSuccessionOfFirstLetter && stringRef.current === event.key) {\n stringRef.current = '';\n prevIndexRef.current = matchIndexRef.current;\n }\n stringRef.current += event.key;\n clearTimeoutIfSet(timeoutIdRef);\n timeoutIdRef.current = window.setTimeout(() => {\n stringRef.current = '';\n prevIndexRef.current = matchIndexRef.current;\n setTypingChange(false);\n }, resetMs);\n const prevIndex = prevIndexRef.current;\n const index = getMatchingIndex(listContent, [...listContent.slice((prevIndex || 0) + 1), ...listContent.slice(0, (prevIndex || 0) + 1)], stringRef.current);\n if (index !== -1) {\n onMatch(index);\n matchIndexRef.current = index;\n } else if (event.key !== ' ') {\n stringRef.current = '';\n setTypingChange(false);\n }\n });\n const reference = React.useMemo(() => ({\n onKeyDown\n }), [onKeyDown]);\n const floating = React.useMemo(() => {\n return {\n onKeyDown,\n onKeyUp(event) {\n if (event.key === ' ') {\n setTypingChange(false);\n }\n }\n };\n }, [onKeyDown, setTypingChange]);\n return React.useMemo(() => enabled ? {\n reference,\n floating\n } : {}, [enabled, reference, floating]);\n}\n\nfunction getArgsWithCustomFloatingHeight(state, height) {\n return {\n ...state,\n rects: {\n ...state.rects,\n floating: {\n ...state.rects.floating,\n height\n }\n }\n };\n}\n/**\n * Positions the floating element such that an inner element inside of it is\n * anchored to the reference element.\n * @see https://floating-ui.com/docs/inner\n * @deprecated\n */\nconst inner = props => ({\n name: 'inner',\n options: props,\n async fn(state) {\n const {\n listRef,\n overflowRef,\n onFallbackChange,\n offset: innerOffset = 0,\n index = 0,\n minItemsVisible = 4,\n referenceOverflowThreshold = 0,\n scrollRef,\n ...detectOverflowOptions\n } = evaluate(props, state);\n const {\n rects,\n platform,\n elements: {\n floating\n }\n } = state;\n const item = listRef.current[index];\n const scrollEl = (scrollRef == null ? void 0 : scrollRef.current) || floating;\n\n // Valid combinations:\n // 1. Floating element is the scrollRef and has a border (default)\n // 2. Floating element is not the scrollRef, floating element has a border\n // 3. Floating element is not the scrollRef, scrollRef has a border\n // Floating > {...getFloatingProps()} wrapper > scrollRef > items is not\n // allowed as VoiceOver doesn't work.\n const clientTop = floating.clientTop || scrollEl.clientTop;\n const floatingIsBordered = floating.clientTop !== 0;\n const scrollElIsBordered = scrollEl.clientTop !== 0;\n const floatingIsScrollEl = floating === scrollEl;\n if (process.env.NODE_ENV !== \"production\") {\n if (!state.placement.startsWith('bottom')) {\n warn('`placement` side must be \"bottom\" when using the `inner`', 'middleware.');\n }\n }\n if (!item) {\n return {};\n }\n const nextArgs = {\n ...state,\n ...(await offset(-item.offsetTop - floating.clientTop - rects.reference.height / 2 - item.offsetHeight / 2 - innerOffset).fn(state))\n };\n const overflow = await platform.detectOverflow(getArgsWithCustomFloatingHeight(nextArgs, scrollEl.scrollHeight + clientTop + floating.clientTop), detectOverflowOptions);\n const refOverflow = await platform.detectOverflow(nextArgs, {\n ...detectOverflowOptions,\n elementContext: 'reference'\n });\n const diffY = max(0, overflow.top);\n const nextY = nextArgs.y + diffY;\n const isScrollable = scrollEl.scrollHeight > scrollEl.clientHeight;\n const rounder = isScrollable ? v => v : round;\n const maxHeight = rounder(max(0, scrollEl.scrollHeight + (floatingIsBordered && floatingIsScrollEl || scrollElIsBordered ? clientTop * 2 : 0) - diffY - max(0, overflow.bottom)));\n scrollEl.style.maxHeight = maxHeight + \"px\";\n scrollEl.scrollTop = diffY;\n\n // There is not enough space, fallback to standard anchored positioning\n if (onFallbackChange) {\n const shouldFallback = scrollEl.offsetHeight < item.offsetHeight * min(minItemsVisible, listRef.current.length) - 1 || refOverflow.top >= -referenceOverflowThreshold || refOverflow.bottom >= -referenceOverflowThreshold;\n ReactDOM.flushSync(() => onFallbackChange(shouldFallback));\n }\n if (overflowRef) {\n overflowRef.current = await platform.detectOverflow(getArgsWithCustomFloatingHeight({\n ...nextArgs,\n y: nextY\n }, scrollEl.offsetHeight + clientTop + floating.clientTop), detectOverflowOptions);\n }\n return {\n y: nextY\n };\n }\n});\n/**\n * Changes the `inner` middleware's `offset` upon a `wheel` event to\n * expand the floating element's height, revealing more list items.\n * @see https://floating-ui.com/docs/inner\n * @deprecated\n */\nfunction useInnerOffset(context, props) {\n const {\n open,\n elements\n } = context;\n const {\n enabled = true,\n overflowRef,\n scrollRef,\n onChange: unstable_onChange\n } = props;\n const onChange = useEffectEvent(unstable_onChange);\n const controlledScrollingRef = React.useRef(false);\n const prevScrollTopRef = React.useRef(null);\n const initialOverflowRef = React.useRef(null);\n React.useEffect(() => {\n if (!enabled) return;\n function onWheel(e) {\n if (e.ctrlKey || !el || overflowRef.current == null) {\n return;\n }\n const dY = e.deltaY;\n const isAtTop = overflowRef.current.top >= -0.5;\n const isAtBottom = overflowRef.current.bottom >= -0.5;\n const remainingScroll = el.scrollHeight - el.clientHeight;\n const sign = dY < 0 ? -1 : 1;\n const method = dY < 0 ? 'max' : 'min';\n if (el.scrollHeight <= el.clientHeight) {\n return;\n }\n if (!isAtTop && dY > 0 || !isAtBottom && dY < 0) {\n e.preventDefault();\n ReactDOM.flushSync(() => {\n onChange(d => d + Math[method](dY, remainingScroll * sign));\n });\n } else if (/firefox/i.test(getUserAgent())) {\n // Needed to propagate scrolling during momentum scrolling phase once\n // it gets limited by the boundary. UX improvement, not critical.\n el.scrollTop += dY;\n }\n }\n const el = (scrollRef == null ? void 0 : scrollRef.current) || elements.floating;\n if (open && el) {\n el.addEventListener('wheel', onWheel);\n\n // Wait for the position to be ready.\n requestAnimationFrame(() => {\n prevScrollTopRef.current = el.scrollTop;\n if (overflowRef.current != null) {\n initialOverflowRef.current = {\n ...overflowRef.current\n };\n }\n });\n return () => {\n prevScrollTopRef.current = null;\n initialOverflowRef.current = null;\n el.removeEventListener('wheel', onWheel);\n };\n }\n }, [enabled, open, elements.floating, overflowRef, scrollRef, onChange]);\n const floating = React.useMemo(() => ({\n onKeyDown() {\n controlledScrollingRef.current = true;\n },\n onWheel() {\n controlledScrollingRef.current = false;\n },\n onPointerMove() {\n controlledScrollingRef.current = false;\n },\n onScroll() {\n const el = (scrollRef == null ? void 0 : scrollRef.current) || elements.floating;\n if (!overflowRef.current || !el || !controlledScrollingRef.current) {\n return;\n }\n if (prevScrollTopRef.current !== null) {\n const scrollDiff = el.scrollTop - prevScrollTopRef.current;\n if (overflowRef.current.bottom < -0.5 && scrollDiff < -1 || overflowRef.current.top < -0.5 && scrollDiff > 1) {\n ReactDOM.flushSync(() => onChange(d => d + scrollDiff));\n }\n }\n\n // [Firefox] Wait for the height change to have been applied.\n requestAnimationFrame(() => {\n prevScrollTopRef.current = el.scrollTop;\n });\n }\n }), [elements.floating, onChange, overflowRef, scrollRef]);\n return React.useMemo(() => enabled ? {\n floating\n } : {}, [enabled, floating]);\n}\n\nfunction getNodeChildren(nodes, id, onlyOpenChildren) {\n if (onlyOpenChildren === void 0) {\n onlyOpenChildren = true;\n }\n const directChildren = nodes.filter(node => {\n var _node$context;\n return node.parentId === id && (!onlyOpenChildren || ((_node$context = node.context) == null ? void 0 : _node$context.open));\n });\n return directChildren.flatMap(child => [child, ...getNodeChildren(nodes, child.id, onlyOpenChildren)]);\n}\n\nfunction isPointInPolygon(point, polygon) {\n const [x, y] = point;\n let isInside = false;\n const length = polygon.length;\n for (let i = 0, j = length - 1; i < length; j = i++) {\n const [xi, yi] = polygon[i] || [0, 0];\n const [xj, yj] = polygon[j] || [0, 0];\n const intersect = yi >= y !== yj >= y && x <= (xj - xi) * (y - yi) / (yj - yi) + xi;\n if (intersect) {\n isInside = !isInside;\n }\n }\n return isInside;\n}\nfunction isInside(point, rect) {\n return point[0] >= rect.x && point[0] <= rect.x + rect.width && point[1] >= rect.y && point[1] <= rect.y + rect.height;\n}\n/**\n * Generates a safe polygon area that the user can traverse without closing the\n * floating element once leaving the reference element.\n * @see https://floating-ui.com/docs/useHover#safepolygon\n */\nfunction safePolygon(options) {\n if (options === void 0) {\n options = {};\n }\n const {\n buffer = 0.5,\n blockPointerEvents = false,\n requireIntent = true\n } = options;\n const timeoutRef = {\n current: -1\n };\n let hasLanded = false;\n let lastX = null;\n let lastY = null;\n let lastCursorTime = typeof performance !== 'undefined' ? performance.now() : 0;\n function getCursorSpeed(x, y) {\n const currentTime = performance.now();\n const elapsedTime = currentTime - lastCursorTime;\n if (lastX === null || lastY === null || elapsedTime === 0) {\n lastX = x;\n lastY = y;\n lastCursorTime = currentTime;\n return null;\n }\n const deltaX = x - lastX;\n const deltaY = y - lastY;\n const distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);\n const speed = distance / elapsedTime; // px / ms\n\n lastX = x;\n lastY = y;\n lastCursorTime = currentTime;\n return speed;\n }\n const fn = _ref => {\n let {\n x,\n y,\n placement,\n elements,\n onClose,\n nodeId,\n tree\n } = _ref;\n return function onMouseMove(event) {\n function close() {\n clearTimeoutIfSet(timeoutRef);\n onClose();\n }\n clearTimeoutIfSet(timeoutRef);\n if (!elements.domReference || !elements.floating || placement == null || x == null || y == null) {\n return;\n }\n const {\n clientX,\n clientY\n } = event;\n const clientPoint = [clientX, clientY];\n const target = getTarget(event);\n const isLeave = event.type === 'mouseleave';\n const isOverFloatingEl = contains(elements.floating, target);\n const isOverReferenceEl = contains(elements.domReference, target);\n const refRect = elements.domReference.getBoundingClientRect();\n const rect = elements.floating.getBoundingClientRect();\n const side = placement.split('-')[0];\n const cursorLeaveFromRight = x > rect.right - rect.width / 2;\n const cursorLeaveFromBottom = y > rect.bottom - rect.height / 2;\n const isOverReferenceRect = isInside(clientPoint, refRect);\n const isFloatingWider = rect.width > refRect.width;\n const isFloatingTaller = rect.height > refRect.height;\n const left = (isFloatingWider ? refRect : rect).left;\n const right = (isFloatingWider ? refRect : rect).right;\n const top = (isFloatingTaller ? refRect : rect).top;\n const bottom = (isFloatingTaller ? refRect : rect).bottom;\n if (isOverFloatingEl) {\n hasLanded = true;\n if (!isLeave) {\n return;\n }\n }\n if (isOverReferenceEl) {\n hasLanded = false;\n }\n if (isOverReferenceEl && !isLeave) {\n hasLanded = true;\n return;\n }\n\n // Prevent overlapping floating element from being stuck in an open-close\n // loop: https://github.com/floating-ui/floating-ui/issues/1910\n if (isLeave && isElement(event.relatedTarget) && contains(elements.floating, event.relatedTarget)) {\n return;\n }\n\n // If any nested child is open, abort.\n if (tree && getNodeChildren(tree.nodesRef.current, nodeId).length) {\n return;\n }\n\n // If the pointer is leaving from the opposite side, the \"buffer\" logic\n // creates a point where the floating element remains open, but should be\n // ignored.\n // A constant of 1 handles floating point rounding errors.\n if (side === 'top' && y >= refRect.bottom - 1 || side === 'bottom' && y <= refRect.top + 1 || side === 'left' && x >= refRect.right - 1 || side === 'right' && x <= refRect.left + 1) {\n return close();\n }\n\n // Ignore when the cursor is within the rectangular trough between the\n // two elements. Since the triangle is created from the cursor point,\n // which can start beyond the ref element's edge, traversing back and\n // forth from the ref to the floating element can cause it to close. This\n // ensures it always remains open in that case.\n let rectPoly = [];\n switch (side) {\n case 'top':\n rectPoly = [[left, refRect.top + 1], [left, rect.bottom - 1], [right, rect.bottom - 1], [right, refRect.top + 1]];\n break;\n case 'bottom':\n rectPoly = [[left, rect.top + 1], [left, refRect.bottom - 1], [right, refRect.bottom - 1], [right, rect.top + 1]];\n break;\n case 'left':\n rectPoly = [[rect.right - 1, bottom], [rect.right - 1, top], [refRect.left + 1, top], [refRect.left + 1, bottom]];\n break;\n case 'right':\n rectPoly = [[refRect.right - 1, bottom], [refRect.right - 1, top], [rect.left + 1, top], [rect.left + 1, bottom]];\n break;\n }\n function getPolygon(_ref2) {\n let [x, y] = _ref2;\n switch (side) {\n case 'top':\n {\n const cursorPointOne = [isFloatingWider ? x + buffer / 2 : cursorLeaveFromRight ? x + buffer * 4 : x - buffer * 4, y + buffer + 1];\n const cursorPointTwo = [isFloatingWider ? x - buffer / 2 : cursorLeaveFromRight ? x + buffer * 4 : x - buffer * 4, y + buffer + 1];\n const commonPoints = [[rect.left, cursorLeaveFromRight ? rect.bottom - buffer : isFloatingWider ? rect.bottom - buffer : rect.top], [rect.right, cursorLeaveFromRight ? isFloatingWider ? rect.bottom - buffer : rect.top : rect.bottom - buffer]];\n return [cursorPointOne, cursorPointTwo, ...commonPoints];\n }\n case 'bottom':\n {\n const cursorPointOne = [isFloatingWider ? x + buffer / 2 : cursorLeaveFromRight ? x + buffer * 4 : x - buffer * 4, y - buffer];\n const cursorPointTwo = [isFloatingWider ? x - buffer / 2 : cursorLeaveFromRight ? x + buffer * 4 : x - buffer * 4, y - buffer];\n const commonPoints = [[rect.left, cursorLeaveFromRight ? rect.top + buffer : isFloatingWider ? rect.top + buffer : rect.bottom], [rect.right, cursorLeaveFromRight ? isFloatingWider ? rect.top + buffer : rect.bottom : rect.top + buffer]];\n return [cursorPointOne, cursorPointTwo, ...commonPoints];\n }\n case 'left':\n {\n const cursorPointOne = [x + buffer + 1, isFloatingTaller ? y + buffer / 2 : cursorLeaveFromBottom ? y + buffer * 4 : y - buffer * 4];\n const cursorPointTwo = [x + buffer + 1, isFloatingTaller ? y - buffer / 2 : cursorLeaveFromBottom ? y + buffer * 4 : y - buffer * 4];\n const commonPoints = [[cursorLeaveFromBottom ? rect.right - buffer : isFloatingTaller ? rect.right - buffer : rect.left, rect.top], [cursorLeaveFromBottom ? isFloatingTaller ? rect.right - buffer : rect.left : rect.right - buffer, rect.bottom]];\n return [...commonPoints, cursorPointOne, cursorPointTwo];\n }\n case 'right':\n {\n const cursorPointOne = [x - buffer, isFloatingTaller ? y + buffer / 2 : cursorLeaveFromBottom ? y + buffer * 4 : y - buffer * 4];\n const cursorPointTwo = [x - buffer, isFloatingTaller ? y - buffer / 2 : cursorLeaveFromBottom ? y + buffer * 4 : y - buffer * 4];\n const commonPoints = [[cursorLeaveFromBottom ? rect.left + buffer : isFloatingTaller ? rect.left + buffer : rect.right, rect.top], [cursorLeaveFromBottom ? isFloatingTaller ? rect.left + buffer : rect.right : rect.left + buffer, rect.bottom]];\n return [cursorPointOne, cursorPointTwo, ...commonPoints];\n }\n }\n }\n if (isPointInPolygon([clientX, clientY], rectPoly)) {\n return;\n }\n if (hasLanded && !isOverReferenceRect) {\n return close();\n }\n if (!isLeave && requireIntent) {\n const cursorSpeed = getCursorSpeed(event.clientX, event.clientY);\n const cursorSpeedThreshold = 0.1;\n if (cursorSpeed !== null && cursorSpeed < cursorSpeedThreshold) {\n return close();\n }\n }\n if (!isPointInPolygon([clientX, clientY], getPolygon([x, y]))) {\n close();\n } else if (!hasLanded && requireIntent) {\n timeoutRef.current = window.setTimeout(close, 40);\n }\n };\n };\n fn.__options = {\n blockPointerEvents\n };\n return fn;\n}\n\nexport { Composite, CompositeItem, FloatingArrow, FloatingDelayGroup, FloatingFocusManager, FloatingList, FloatingNode, FloatingOverlay, FloatingPortal, FloatingTree, NextFloatingDelayGroup, inner, safePolygon, useClick, useClientPoint, useDelayGroup, useDelayGroupContext, useDismiss, useFloating, useFloatingNodeId, useFloatingParentNodeId, useFloatingPortalNode, useFloatingRootContext, useFloatingTree, useFocus, useHover, useId, useInnerOffset, useInteractions, useListItem, useListNavigation, useMergeRefs, useNextDelayGroup, useRole, useTransitionStatus, useTransitionStyles, useTypeahead };\n","/**\n * utils 自带的最小多语言。\n *\n * 原则(需求文档 §5.4):**核心提供什么,核心就负责它的多语言** —— utils 里要吐文案的函数\n * (如相对时间)自带中英字典;插件**自己界面**的文案仍由插件自己管,这里不提供插件级 i18n 框架。\n * 需要覆盖时传自己的 `t` 进来即可。\n */\nconst DICT = {\n zh: {\n sessionLoading: '加载会话…',\n sessionFailed: '会话加载失败',\n sessionEmpty: '该会话暂无内容',\n explorerLoading: '加载中…',\n explorerFailed: '加载失败',\n explorerRoot: '工作区',\n explorerTruncated: '条目过多,已截断',\n explorerEmptyDir: '空目录',\n explorerLevels: '选择层级',\n explorerExpand: '展开',\n explorerCollapse: '收起',\n explorerEnter: '进入',\n explorerRootName: '(工作区根目录)',\n explorerCrumbsAria: '目录路径',\n explorerPickFile: '选择此文件',\n explorerPickDir: '选择',\n explorerPickDirAria: '选择此目录(连带其下所有文件)',\n previewClose: '关闭',\n previewCopyPath: '复制路径',\n previewRefresh: '刷新',\n previewRender: '预览',\n previewSource: '源码',\n previewMdSwitchAria: '切换渲染或源码',\n previewHtmlSwitchAria: '切换渲染或源码',\n previewLoadMore: '加载更多',\n previewTruncated: '内容过大,仅显示前 {n}',\n previewOfficeUnavailable: 'Office 预览不可用',\n previewRenderFailed: '预览渲染失败',\n previewBadPayload: '返回数据不符合预期',\n previewOutside: '路径在工作区之外',\n previewNotFound: '文件不存在',\n previewNotDirectory: '不是文件夹',\n previewTooLarge: '文件过大,无法预览',\n previewNotText: '不是文本文件',\n previewFailedCode: '加载失败({code})',\n mdCopy: '复制',\n mdCopied: '已复制',\n mdCode: '代码',\n mdWrap: '换行',\n mdUnwrap: '取消换行',\n mdFootnotes: '脚注',\n cardToggle: '展开/收起',\n modalClose: '关闭',\n dockClose: '关闭面板',\n dockResize: '拖动调整宽度',\n errorRetry: '重试',\n confirm: '确定',\n cancel: '取消',\n dialogOk: '知道了',\n pickerPlaceholder: '请选择',\n pickerClear: '不选',\n pickerEmpty: '暂无可选',\n pickerNoMatch: '无匹配项',\n pickerSearch: '搜索…',\n pickerSelected: '已选 {n} 项',\n pickerMaxReached: '最多选 {n} 项',\n pickerDegraded: '候选可能不完整',\n modelProvider: '供应商',\n modelModel: '模型',\n modelDefault: '默认模型',\n workspaceAll: '所有工作区',\n relNow: '刚刚',\n relInJustNow: '即将',\n relInMinutes: '{n} 分钟后',\n relInHours: '{n} 小时后',\n relInDays: '{n} 天后',\n relInMonths: '{n} 个月后',\n relInYears: '{n} 年后',\n relJustNow: '刚刚',\n relMinutesAgo: '{n} 分钟前',\n relHoursAgo: '{n} 小时前',\n relDaysAgo: '{n} 天前',\n relWeeksAgo: '{n} 周前',\n relMonthsAgo: '{n} 个月前',\n relYearsAgo: '{n} 年前',\n codeCopy: '复制',\n codeCopied: '已复制',\n sessionUnknownKind: '未支持的节点类型:',\n sessionLoadOlder: '加载更早记录',\n sessionProcess: '过程',\n triggerRequest: '收到执行请求',\n triggerGoal: '继续执行目标',\n triggerAgent: '收到任务消息',\n triggerTeam: '收到团队消息',\n triggerSubagent: '子任务状态更新',\n triggerGithub: '收到 GitHub 事件',\n triggerWebhook: '收到外部事件',\n triggerSchedule: '定时任务',\n triggerJob: '后台任务状态更新',\n triggerPlugin: '插件状态更新',\n triggerExplanation: '这条通知触发了本轮回复。',\n turnProcessTook: '用时 {duration}',\n turnProcessDeepDiving: '深度求索中,用时{duration}',\n turnProcessWorked: '已完成工作',\n turnProcessFailed: '处理失败',\n turnStopped: '已停止',\n chatDeepDiving: '深度求索中',\n thinkLabel: '思考',\n durationSeconds: '{seconds}秒',\n durationMinutes: '{minutes}分{seconds}秒',\n durationHours: '{hours}小时{minutes}分{seconds}秒',\n durationMilliseconds: '{milliseconds}毫秒',\n retryActive: '正在重试模型请求',\n retryCancelled: '模型请求重试已取消',\n retryStarted: '已重试模型请求',\n retryScheduled: '等待重试模型请求',\n retryStatus: '{label}({retry}/{maximum}) · {seconds}s',\n retryDelay: '重试延迟:',\n retryFailure: '失败原因:',\n turnErrorTitle: '本轮运行失败',\n accountStopped: '任务已停止',\n maxTokensTitle: '已达到输出 token 上限',\n maxTokensHint: '回答被截断,已有输出保留在对话中。发送“继续”可让模型接着输出。',\n failureAuth: 'API 密钥无效',\n failureQuota: '当前请求的额度已用尽',\n failureAccountSignedOut: '任务已因退出 DeepSeek 登录而停止。',\n failureAccountSignInRequired: '请先登录 DeepSeek,并确认请求地址支持账号认证。',\n clockDate: '{m}月{d}日',\n clockDateYear: '{y}年{m}月{d}日',\n copyLabel: '复制',\n copiedLabel: '已复制',\n branchLabel: '在新对话中分支',\n branchUnavailableLabel: '只读会话记录不可分支',\n turnUsageTitle: '本轮用量',\n turnUsageModel: '提供方 / 模型',\n turnUsageCacheHit: '缓存命中',\n turnUsageInput: '未缓存输入',\n turnUsageCacheRead: '缓存读取',\n turnUsageCacheWrite: '缓存写入',\n turnUsageOutput: '输出',\n turnUsageReasoning: '(其中推理 {tokens})',\n turnUsageConsumed: '用量 {total}',\n turnUsageCount: '{count} tok',\n numberThousand: '{value}K',\n numberMillion: '{value}M',\n numberGroupSeparator: ',',\n stepProcessDoneThinking: '已完成分析',\n stepProcessDoneRead: '已读取文件',\n stepProcessDoneReadImage: '已读取图片',\n stepProcessDoneWrite: '已写入文件',\n stepProcessDoneSearch: '已搜索代码',\n stepProcessDoneEdit: '修改了文件',\n stepProcessDoneCommands: '执行了命令',\n stepProcessDoneCode: '运行了代码',\n stepProcessDoneWebSearch: '已搜索网页',\n stepProcessDoneWebFetch: '已访问网页',\n stepProcessDoneSubagents: '已协调子智能体',\n stepProcessDonePlan: '更新了计划',\n stepProcessDoneQuestions: '向用户提出了问题',\n stepProcessDoneTools: '已调用工具',\n stepProcessJoinTwo: '{first}并{second}',\n stepProcessComma: ',',\n stepProcessSharedPrefix: '已',\n stepProcessMore: '{title}等',\n toolTitleRead: '读取',\n toolTitleReadImage: '读取图片',\n toolTitleGrep: '搜索文件内容',\n toolTitleGlob: '查找文件',\n toolTitleBash: '运行命令',\n toolTitleWrite: '写入',\n toolTitleEdit: '编辑',\n toolTitleCode: '代码',\n toolTitleWebSearch: '网页搜索',\n toolTitleWebFetch: '网页获取',\n toolTitleGeneric: '工具调用',\n toolTitleSearch: '搜索',\n toolInputLabel: '输入',\n toolOutputLabel: '输出',\n rowPreparing: '正在准备调用',\n rowRunning: '运行中',\n rowFailed: '失败',\n rowStopped: '已停止',\n commandRunning: '执行中…',\n commandFailed: '指令失败',\n commandDone: '已完成',\n commandTitle: '指令',\n collapseLabel: '收起',\n readWindow: '显示 {shown} / {total} 行',\n readCollapseAria: '收起内容',\n readExpandAria: '展开其余 {count} 行',\n readExpandRest: '… 其余 {count} 行',\n terminalSignal: '信号 {signal}',\n terminalExitCode: '退出码 {code}',\n terminalNoExitCode: '未正常退出',\n terminalRunning: '运行中',\n terminalFailed: '失败',\n terminalDone: '已完成',\n terminalNoOutput: '无输出',\n terminalCollapseAria: '收起输出',\n terminalExpandAria: '展开其余 {n} 行输出',\n terminalExpandRest: '… 其余 {n} 行',\n terminalCommandLine: '第 {n} 行',\n terminalSendInput: '(发送输入)',\n terminalSession: '终端 {sessionId}',\n codeBlockLabel: '代码块',\n diffWrapLabel: '自动换行',\n diffUnwrapLabel: '取消换行',\n diffCollapseAria: '收起差异',\n diffExpandAria: '展开其余 {count} 行差异',\n diffExpandRest: '… 其余 {count} 行',\n sessionArchived: '已归档',\n sessionHeading: '会话预览',\n changesSingle: '已编辑 {name}',\n changesMulti: '已编辑 {count} 个文件',\n changesBinary: '二进制文件',\n changesAll: '全部 {count} 个文件',\n changesCollapse: '收起',\n changesOversized: '文件过大',\n // ── 单文件改动预览(官方 ui-deliverables diff.* 词典逐条对应)──\n diffLoading: '正在读取改动…',\n diffMissing: '这轮改动的内容已不可用',\n diffError: '无法读取改动',\n diffBinary: '二进制文件,无法显示改动',\n diffOversized: '文件过大,无法显示改动',\n diffCreated: '本轮新建的文件',\n diffDeleted: '本轮删除的文件',\n diffUnchanged: '两侧内容相同',\n diffCoarse: '逐行对比超时,按整个文件替换显示',\n diffTruncated: '只显示前 {count} 行',\n continueBranch: '继续对话',\n forkConfirmTitle: '开分支继续对话',\n forkConfirmText: '是否需要基于此会话开一个新分支继续对话?原会话保持只读留档,新分支复制本会话内容并可继续对话。',\n forkConfirmAccept: '开分支并跳转',\n forkWorking: '正在开分支…',\n forkFailed: '开分支失败:{error}',\n deliverRowTitle: '交付文件',\n deliverRowPreparing: '准备交付',\n deliverRowRunning: '正在交付',\n deliverRowOk: '已交付',\n deliverRowError: '交付失败',\n deliverRowStopped: '已中断',\n deliverFileLabel: '文件',\n deliverPreviewHint: '预览',\n deliverPreviewCard: '预览 {name}',\n deliverAll: '全部 {count} 个文件',\n deliverCollapse: '收起',\n deliverExpandAria: '展开全部 {count} 个交付文件',\n deliverCollapseAria: '收起交付文件列表',\n composerPlaceholder: '继续说点什么…',\n composerHint: '点「确定」后基于本会话开分支,并在官方会话中开始这轮对话',\n dtPlaceholder: '请选择日期时间',\n dtStart: '开始',\n dtEnd: '结束',\n dtToday: '今天',\n dtNow: '现在',\n dtClear: '清除',\n dtHour: '时',\n dtMinute: '分',\n dtSecond: '秒',\n dtPrevYear: '上一年',\n dtPrevMonth: '上一月',\n dtNextMonth: '下一月',\n dtNextYear: '下一年',\n dtInvalidRange: '结束时间早于开始时间',\n },\n en: {\n sessionLoading: 'Loading session…',\n sessionFailed: 'Failed to load session',\n sessionEmpty: 'No content in this session',\n explorerLoading: 'Loading…',\n explorerFailed: 'Failed to load',\n explorerRoot: 'Workspace',\n explorerTruncated: 'Too many entries, truncated',\n explorerEmptyDir: 'Empty folder',\n explorerLevels: 'Jump to level',\n explorerExpand: 'Expand',\n explorerCollapse: 'Collapse',\n explorerEnter: 'Open',\n explorerRootName: '(workspace root)',\n explorerCrumbsAria: 'Breadcrumb',\n explorerPickFile: 'Pick this file',\n explorerPickDir: 'Select',\n explorerPickDirAria: 'Pick this folder (with everything under it)',\n previewClose: 'Close',\n previewCopyPath: 'Copy path',\n previewRefresh: 'Refresh',\n previewRender: 'Preview',\n previewSource: 'Source',\n previewMdSwitchAria: 'Toggle render or source',\n previewHtmlSwitchAria: 'Toggle render or source',\n previewLoadMore: 'Load more',\n previewTruncated: 'Content too large, showing first {n}',\n previewOfficeUnavailable: 'Office preview unavailable',\n previewRenderFailed: 'Failed to render preview',\n previewBadPayload: 'Unexpected response payload',\n previewOutside: 'Path is outside the workspace',\n previewNotFound: 'File not found',\n previewNotDirectory: 'Not a folder',\n previewTooLarge: 'File too large to preview',\n previewNotText: 'Not a text file',\n previewFailedCode: 'Failed to load ({code})',\n mdCopy: 'Copy',\n mdCopied: 'Copied',\n mdCode: 'Code',\n mdWrap: 'Wrap',\n mdUnwrap: 'Unwrap',\n mdFootnotes: 'Footnotes',\n cardToggle: 'Expand/Collapse',\n modalClose: 'Close',\n dockClose: 'Close panel',\n dockResize: 'Drag to resize',\n errorRetry: 'Retry',\n confirm: 'Confirm',\n cancel: 'Cancel',\n dialogOk: 'OK',\n pickerPlaceholder: 'Select…',\n pickerClear: 'None',\n pickerEmpty: 'No options',\n pickerNoMatch: 'No match',\n pickerSearch: 'Search…',\n pickerSelected: '{n} selected',\n pickerMaxReached: 'Up to {n}',\n pickerDegraded: 'List may be incomplete',\n modelProvider: 'Provider',\n modelModel: 'Model',\n modelDefault: 'Default model',\n workspaceAll: 'All workspaces',\n relNow: 'just now',\n relInJustNow: 'soon',\n relInMinutes: 'in {n}m',\n relInHours: 'in {n}h',\n relInDays: 'in {n}d',\n relInMonths: 'in {n}mo',\n relInYears: 'in {n}y',\n relJustNow: 'just now',\n relMinutesAgo: '{n}m ago',\n relHoursAgo: '{n}h ago',\n relDaysAgo: '{n}d ago',\n relWeeksAgo: '{n}w ago',\n relMonthsAgo: '{n}mo ago',\n relYearsAgo: '{n}y ago',\n codeCopy: 'Copy',\n codeCopied: 'Copied',\n sessionUnknownKind: 'Unsupported node kind: ',\n sessionLoadOlder: 'Load earlier messages',\n sessionProcess: 'Process',\n triggerRequest: 'Execution request received',\n triggerGoal: 'Continuing the goal',\n triggerAgent: 'Task message received',\n triggerTeam: 'Team message received',\n triggerSubagent: 'Subagent status update',\n triggerGithub: 'GitHub event received',\n triggerWebhook: 'External event received',\n triggerSchedule: 'Scheduled task',\n triggerJob: 'Background task status update',\n triggerPlugin: 'Plugin status update',\n triggerExplanation: 'This notification triggered the reply below.',\n turnProcessTook: 'Took {duration}',\n turnProcessDeepDiving: 'Thinking, {duration}',\n turnProcessWorked: 'Work completed',\n turnProcessFailed: 'Failed',\n turnStopped: 'Stopped',\n chatDeepDiving: 'Thinking',\n thinkLabel: 'Think',\n durationSeconds: '{seconds}s',\n durationMinutes: '{minutes}m {seconds}s',\n durationHours: '{hours}h {minutes}m {seconds}s',\n durationMilliseconds: '{milliseconds}ms',\n retryActive: 'Retrying model request',\n retryCancelled: 'Model request retry cancelled',\n retryStarted: 'Retried model request',\n retryScheduled: 'Waiting to retry model request',\n retryStatus: '{label} ({retry}/{maximum}) · {seconds}s',\n retryDelay: 'Retry delay: ',\n retryFailure: 'Failure reason: ',\n turnErrorTitle: 'This turn failed',\n accountStopped: 'Task stopped',\n maxTokensTitle: 'Output token limit reached',\n maxTokensHint: 'The reply was cut off; earlier output is preserved in the conversation. Send \"continue\" to let the model resume.',\n failureAuth: 'API key is invalid',\n failureQuota: 'Request quota exhausted.',\n failureAccountSignedOut: 'Stopped because you signed out of DeepSeek.',\n failureAccountSignInRequired: 'Sign in to DeepSeek and ensure the request destination supports account authentication.',\n clockDate: '{m}/{d}',\n clockDateYear: '{y}/{m}/{d}',\n copyLabel: 'Copy',\n copiedLabel: 'Copied',\n branchLabel: 'Branch into a new conversation',\n branchUnavailableLabel: 'A read-only transcript cannot be branched',\n turnUsageTitle: 'Turn usage',\n turnUsageModel: 'Provider / model',\n turnUsageCacheHit: 'Cache hit',\n turnUsageInput: 'Uncached input',\n turnUsageCacheRead: 'Cached input',\n turnUsageCacheWrite: 'Cache write',\n turnUsageOutput: 'Output',\n turnUsageReasoning: ' ({tokens} reasoning)',\n turnUsageConsumed: 'Usage {total}',\n turnUsageCount: '{count} tok',\n numberThousand: '{value}K',\n numberMillion: '{value}M',\n numberGroupSeparator: ',',\n stepProcessDoneThinking: 'Analysis completed',\n stepProcessDoneRead: 'Read files',\n stepProcessDoneReadImage: 'Read images',\n stepProcessDoneWrite: 'Wrote files',\n stepProcessDoneSearch: 'Searched code',\n stepProcessDoneEdit: 'Edited files',\n stepProcessDoneCommands: 'Ran commands',\n stepProcessDoneCode: 'Ran code',\n stepProcessDoneWebSearch: 'Searched the web',\n stepProcessDoneWebFetch: 'Fetched web pages',\n stepProcessDoneSubagents: 'Coordinated subagents',\n stepProcessDonePlan: 'Updated the plan',\n stepProcessDoneQuestions: 'Asked you questions',\n stepProcessDoneTools: 'Called tools',\n stepProcessJoinTwo: '{first} and {second}',\n stepProcessComma: ', ',\n stepProcessSharedPrefix: '',\n stepProcessMore: '{title}, etc.',\n toolTitleRead: 'Read',\n toolTitleReadImage: 'Read image',\n toolTitleGrep: 'Grep',\n toolTitleGlob: 'Glob',\n toolTitleBash: 'Bash',\n toolTitleWrite: 'Write',\n toolTitleEdit: 'Edit',\n toolTitleCode: 'Code',\n toolTitleWebSearch: 'Search',\n toolTitleWebFetch: 'Fetch',\n toolTitleGeneric: 'Tool call',\n toolTitleSearch: 'Search',\n toolInputLabel: 'IN',\n toolOutputLabel: 'OUT',\n rowPreparing: 'Preparing tool call',\n rowRunning: 'Running',\n rowFailed: 'Failed',\n rowStopped: 'Stopped',\n commandRunning: 'Running…',\n commandFailed: 'Command failed',\n commandDone: 'Completed',\n commandTitle: 'Command',\n collapseLabel: 'Collapse',\n readWindow: 'Showing {shown} of {total} lines',\n readCollapseAria: 'Collapse content',\n readExpandAria: 'Expand {count} more lines',\n readExpandRest: '… {count} more lines',\n terminalSignal: 'signal {signal}',\n terminalExitCode: 'exit code {code}',\n terminalNoExitCode: 'no exit code',\n terminalRunning: 'Running',\n terminalFailed: 'Failed',\n terminalDone: 'Done',\n terminalNoOutput: 'No output',\n terminalCollapseAria: 'Collapse output',\n terminalExpandAria: 'Expand the remaining {n} output lines',\n terminalExpandRest: '… {n} more lines',\n terminalCommandLine: 'line {n}',\n terminalSendInput: '(send input)',\n terminalSession: 'Terminal {sessionId}',\n codeBlockLabel: 'Code',\n diffWrapLabel: 'Wrap lines',\n diffUnwrapLabel: 'Unwrap lines',\n diffCollapseAria: 'Collapse diff',\n diffExpandAria: 'Expand {count} more diff lines',\n diffExpandRest: '… {count} more lines',\n sessionArchived: 'Archived',\n sessionHeading: 'Session preview',\n changesSingle: 'Edited {name}',\n changesMulti: 'Edited {count} files',\n changesBinary: 'Binary file',\n changesAll: 'All {count} files',\n changesCollapse: 'Collapse',\n changesOversized: 'File too large',\n diffLoading: 'Reading changes…',\n diffMissing: 'The contents of this turn’s changes are no longer available',\n diffError: 'Could not read the changes',\n diffBinary: 'Binary file; changes cannot be shown',\n diffOversized: 'File too large; changes cannot be shown',\n diffCreated: 'Created in this turn',\n diffDeleted: 'Deleted in this turn',\n diffUnchanged: 'Both sides hold the same lines',\n diffCoarse: 'Line comparison timed out; shown as a whole-file replacement',\n diffTruncated: 'Showing the first {count} lines',\n continueBranch: 'Continue conversation',\n forkConfirmTitle: 'Fork to continue',\n forkConfirmText: 'Start a new branch from this session to continue the conversation? The original stays read-only; the branch copies this conversation and can continue.',\n forkConfirmAccept: 'Fork & open',\n forkWorking: 'Forking…',\n forkFailed: 'Fork failed: {error}',\n deliverRowTitle: 'Deliver files',\n deliverRowPreparing: 'Preparing delivery',\n deliverRowRunning: 'Delivering',\n deliverRowOk: 'Delivered',\n deliverRowError: 'Delivery failed',\n deliverRowStopped: 'Interrupted',\n deliverFileLabel: 'File',\n deliverPreviewHint: 'Preview',\n deliverPreviewCard: 'Preview {name}',\n deliverAll: 'All {count} files',\n deliverCollapse: 'Collapse',\n deliverExpandAria: 'Expand all {count} delivered files',\n deliverCollapseAria: 'Collapse the delivered-files list',\n composerPlaceholder: 'Say something to continue…',\n composerHint: 'Confirm forks a branch from this session and starts this turn in the official chat',\n dtPlaceholder: 'Select date & time',\n dtStart: 'Start',\n dtEnd: 'End',\n dtToday: 'Today',\n dtNow: 'Now',\n dtClear: 'Clear',\n dtHour: 'h',\n dtMinute: 'm',\n dtSecond: 's',\n dtPrevYear: 'Previous year',\n dtPrevMonth: 'Previous month',\n dtNextMonth: 'Next month',\n dtNextYear: 'Next year',\n dtInvalidRange: 'End is before start',\n },\n};\nlet current = 'zh';\nexport function setLocale(locale) {\n current = locale;\n}\nexport function getLocale() {\n return current;\n}\n/** 用内置字典翻译一个 key;未知 key 直接回退 key 本身(不抛、不空白)。 */\nexport function t(key, vars) {\n const template = DICT[current][key] ?? DICT.zh[key] ?? key;\n if (vars === undefined)\n return template;\n return template.replace(/\\{(\\w+)\\}/g, (whole, name) => {\n const value = vars[name];\n return value === undefined ? whole : String(value);\n });\n}\n//# sourceMappingURL=i18n.js.map","let renderer;\n/** 注入官方 Tooltip(插件启动时调一次;传 undefined 撤销,回到自绘降级)。 */\nexport function setTooltipRenderer(fn) {\n renderer = fn;\n}\n/** 当前注入的 renderer;未注入返回 undefined(FieldHint 据此走降级路径)。 */\nexport function getTooltipRenderer() {\n return renderer;\n}\n//# sourceMappingURL=tooltip.js.map","/**\n * 问号提示 —— **全站唯一实现、独立组件**(L2,P4)\n *\n * ⚠️ 它**不属于 Input 家族**:任何地方都能挂——表单行尾、标题后面、卡片角落……\n * 调用点自己把它排进自己的 flex / label 里即可(组件只是 14px 的内联图标 + 气泡)。\n *\n * 气泡渲染 = **官方 Tooltip 本体**(2026-10-19 用户拍板「必须和悬停提示用同一个」):\n * 插件启动时 `setTooltipRenderer` 把官方 Tooltip 交给 core,本组件直接走它。\n * ⚠️ **不做降级兜底**(用户同日明确:宿主内官方包恒在;官方改版 = 我们重新适配,不另造一套)。\n * 未注入 renderer 的环境(node 自检)只出问号图标、没有气泡——那是非宿主环境,不是产品形态。\n */\nimport { ensureControls } from './css.js';\nimport { getTooltipRenderer } from './tooltip.js';\nimport { createElement as h } from 'react';\n/** 问号提示图标:hover / focus 浮出说明气泡(官方 Tooltip 渲染)。 */\nexport function FieldHint(props) {\n ensureControls();\n const { text, side, align, maxWidth, className, style } = props;\n // 官方往子元素挂 ref / 事件 ⇒ 锚点必须是真实 DOM 元素(兄弟仓踩过两次的坑),这里恒为原生 span。\n const anchor = h('span', {\n className: `dshpc-hint${className !== undefined && className !== '' ? ` ${className}` : ''}`,\n style,\n tabIndex: 0,\n role: 'note',\n 'aria-label': text,\n }, '?');\n const renderer = getTooltipRenderer();\n // 宿主内 renderer 恒被注入(demo 与各插件启动时做一次);未注入 ⇒ 非宿主环境,只出图标。\n if (renderer === undefined)\n return anchor;\n return renderer({\n label: text,\n side: side ?? 'top',\n ...(align !== undefined ? { align } : {}),\n ...(maxWidth !== undefined ? { maxWidth } : {}),\n children: anchor,\n });\n}\n//# sourceMappingURL=FieldHint.js.map","import { createElement as h, useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport { useFloating, FloatingPortal, flip, shift, offset, autoUpdate, size as floatingSize } from '@floating-ui/react';\nimport { ensureControls } from './css.js';\nimport { t } from '../utils/i18n.js';\nimport { FieldHint } from './FieldHint.js';\nimport { filterGroups, flattenOptions, labelsOf, toGroups, toggleValue, } from './picker-logic.js';\n/**\n * 通用选择器:单选 / 多选 / 上限 / 搜索 / 分组 / 空态 / 降级。\n *\n * **纯零件,不自己取数** —— 选项由调用方传入(工作区列表、模型列表这类数据要跨 host↔client\n * 边界,通道是插件私有的,组件取不到,见需求文档 §6)。\n */\nexport function Picker(props) {\n ensureControls();\n const tt = props.translate ?? t;\n const mode = props.mode ?? 'single';\n const size = props.size ?? 'md';\n const placement = props.placement ?? 'down';\n const clearable = props.clearable === true;\n const showLabels = props.showLabels !== false;\n const groups = useMemo(() => toGroups(props.groups, props.options), [props.groups, props.options]);\n const controlled = props.value !== undefined;\n const [inner, setInner] = useState(() => toArray(props.defaultValue));\n const selected = controlled\n ? toArray(props.value)\n : inner;\n const emit = (next) => {\n if (!controlled)\n setInner(next);\n props.onChange?.(mode === 'single' ? (next[0] ?? '') : next);\n };\n const [open, setOpen] = useState(false);\n const [query, setQuery] = useState('');\n const [active, setActive] = useState(-1);\n const rootRef = useRef(null);\n const searchRef = useRef(null);\n // 浮层定位:portal 到 body + viewport 相对 + 滚动/缩放自动跟随 + 贴边自动翻转,\n // 彻底避开祖先 overflow/transform 裁剪(核心缺陷修复)。宽度/最大高由 size 中间件内联设置。\n const { refs, floatingStyles } = useFloating({\n open,\n onOpenChange: setOpen,\n placement: placement === 'up' ? 'top-start' : 'bottom-start',\n middleware: [\n offset(4),\n flip(),\n shift({ padding: 8 }),\n floatingSize({\n apply({ elements, rects, availableWidth, availableHeight }) {\n Object.assign(elements.floating.style, {\n // 触发器可以限宽,菜单不能跟着限:至少与触发器同宽,随内容变宽,封顶 480 免得太夸张\n minWidth: `${rects.reference.width}px`,\n maxWidth: `${Math.min(480, availableWidth ?? 480)}px`,\n maxHeight: `${Math.max(80, Math.min(280, (availableHeight ?? 320) - 8))}px`,\n });\n },\n }),\n ],\n whileElementsMounted: autoUpdate,\n strategy: 'fixed',\n });\n // 展开即聚焦搜索框(2026-10-20 用户:点开就能直接打字,不用再点一下)。\n // 用回调 ref 在搜索框「真正挂载」时聚焦:菜单经 FloatingPortal 延后挂载,\n // 普通 useEffect(open) 会在输入框还没挂上时跑(searchRef 仍为 null),导致失效。\n const setSearchRef = useCallback((el) => {\n searchRef.current = el;\n if (el !== null && open)\n el.focus();\n }, [open]);\n // 点外面收起(同时认 root 与浮层两个 DOM 子树:菜单 portal 到 body 后不在 root 内)\n useEffect(() => {\n if (!open)\n return;\n const onDown = (e) => {\n const root = rootRef.current;\n const floatingEl = refs.floating.current;\n if (root !== null && root.contains(e.target))\n return;\n if (floatingEl !== null && floatingEl.contains(e.target))\n return;\n setOpen(false);\n };\n document.addEventListener('mousedown', onDown);\n return () => document.removeEventListener('mousedown', onDown);\n }, [open]);\n // 收起时清掉搜索词与键盘游标,别让下次打开带着上次的过滤条件\n useEffect(() => {\n if (open)\n return;\n setQuery('');\n setActive(-1);\n }, [open]);\n const shown = filterGroups(groups, query);\n const flat = flattenOptions(shown);\n const atMax = mode === 'multiple' && props.max !== undefined && selected.length >= props.max;\n const summary = selected.length === 0\n ? (props.placeholder ?? tt('pickerPlaceholder'))\n : mode === 'multiple' && !showLabels\n ? tt('pickerSelected', { n: selected.length })\n : labelsOf(groups, selected).join('、') || (props.placeholder ?? tt('pickerPlaceholder'));\n const pick = (value) => {\n if (mode === 'single') {\n emit([value]);\n setOpen(false);\n return;\n }\n emit(toggleValue(selected, value, props.max));\n if (props.closeOnSelect === true)\n setOpen(false);\n };\n const clear = () => {\n emit([]);\n setOpen(false);\n };\n // 键盘可达:Esc 关、上下移、回车选(没有 aria 树那么全,但能用键盘走完一遍)\n const onKeyDown = (e) => {\n if (!open)\n return;\n if (e.key === 'Escape') {\n setOpen(false);\n return;\n }\n if (flat.length === 0)\n return;\n if (e.key === 'ArrowDown' || e.key === 'ArrowUp') {\n e.preventDefault();\n const dir = e.key === 'ArrowDown' ? 1 : -1;\n setActive((cur) => (cur + dir + flat.length) % flat.length);\n return;\n }\n if (e.key === 'Enter' && active >= 0) {\n e.preventDefault();\n const hit = flat[active];\n if (hit !== undefined)\n pick(hit.value);\n }\n };\n // 触发器(右侧箭头 = 内联 SVG chevron,与官方 ⌄ 同形;ui 零官方依赖故自绘)。\n const trigger = h('button', {\n type: 'button',\n 'aria-label': props.ariaLabel,\n 'aria-expanded': open,\n ref: refs.setReference,\n className: `dshpc-picker__trigger dshpc-picker__trigger--${size}${props.align === 'center' ? ' dshpc-picker__trigger--center' : ''}`,\n disabled: props.disabled === true,\n onClick: () => {\n if (props.disabled !== true)\n setOpen(!open);\n },\n }, props.icon !== undefined && props.icon !== null\n ? h('span', { className: 'dshpc-picker__icon' }, props.icon)\n : null, \n // 文字吃掉剩余宽度并靠左(默认):否则 space-between 会把短文案推到中间\n h('span', { className: 'dshpc-picker__label' }, summary), h('svg', {\n className: 'dshpc-picker__caret',\n width: 12,\n height: 12,\n viewBox: '0 0 16 16',\n fill: 'none',\n 'aria-hidden': true,\n }, h('path', {\n d: 'M4 6l4 4 4-4',\n stroke: 'currentColor',\n 'stroke-width': 1.5,\n 'stroke-linecap': 'round',\n 'stroke-linejoin': 'round',\n })));\n // hint 给了就把触发器与 FieldHint 包进同一行(间距/对齐收进组件)。\n const triggerRow = props.hint === undefined\n ? trigger\n : h('span', { className: 'dshpc-fieldwrap dshpc-fieldwrap--inline' }, trigger, h(FieldHint, { text: props.hint }));\n return h('div', {\n className: `dshpc-picker${props.className === undefined ? '' : ` ${props.className}`}`,\n ref: rootRef,\n onKeyDown,\n }, triggerRow, open\n ? h(FloatingPortal, null, h('div', {\n className: 'dshpc-picker__menu',\n ref: refs.setFloating,\n style: floatingStyles,\n }, props.degraded === true\n ? h('div', { className: 'dshpc-picker__degraded' }, tt('pickerDegraded'))\n : null, atMax ? h('div', { className: 'dshpc-picker__degraded' }, tt('pickerMaxReached', { n: props.max ?? 0 })) : null, props.searchable === true\n ? h('input', {\n ref: setSearchRef,\n className: 'dshpc-picker__search',\n placeholder: tt('pickerSearch'),\n value: query,\n onChange: (e) => setQuery(e.target.value),\n })\n : null, flat.length === 0 && groups.length === 0\n ? h('div', { className: 'dshpc-picker__empty' }, tt('pickerEmpty'))\n : flat.length === 0\n ? h('div', { className: 'dshpc-picker__empty' }, tt('pickerNoMatch'))\n : [\n clearable && mode === 'single' && selected.length > 0\n ? h('div', {\n key: '__clear__',\n className: 'dshpc-picker__option dshpc-picker__option--clear',\n onClick: clear,\n }, tt('pickerClear'))\n : null,\n ...shown.map((g) => h('div', { key: g.value || '_' }, g.label === ''\n ? null\n : h('div', { className: 'dshpc-picker__group-label' }, g.label), g.options.map((o) => {\n // 到上限后:未选项置灰,**已选项保持可点**(点了是取消,不是再加)。\n const blocked = o.disabled === true || (atMax && !selected.includes(o.value));\n const activeCls = [\n 'dshpc-picker__option',\n selected.includes(o.value) ? 'dshpc-picker__option--active' : '',\n blocked ? 'dshpc-picker__option--disabled' : '',\n ]\n .filter((s) => s !== '')\n .join(' ');\n const idx = flat.indexOf(o);\n return h('div', {\n key: o.value,\n className: activeCls,\n 'data-active': idx === active ? 'true' : undefined,\n onClick: () => {\n if (!blocked)\n pick(o.value);\n },\n }, mode === 'multiple'\n ? h('span', { className: 'dshpc-picker__tick' }, selected.includes(o.value) ? '✓' : '')\n : null, o.icon !== undefined && o.icon !== null\n ? h('span', { className: 'dshpc-picker__option-icon' }, o.icon)\n : null, h('span', null, o.label));\n }))),\n ]))\n : null);\n}\nfunction toArray(v) {\n if (v === undefined)\n return [];\n return Array.isArray(v) ? [...v] : [v];\n}\n//# sourceMappingURL=Picker.js.map","/**\n * 按钮 / 图标钮 —— **全站唯一实现**(L2 组件皮肤,P2)\n *\n * 三轴模型:\n * - `variant`:外观档(形态 + 语义色),共 10 档\n * primary(黑实心)/ secondary(灰实心)/ outline(描边)/ ghost(无底无边)\n * danger(红实心)/ success(绿实心)/ warning(黄实心)/ info(蓝实心)\n * danger-outline(红字描边)/ link(行内链接)\n * - `size`:`sm`(24) / `md`(28) / `lg`(32) —— 高度一律吃 `--dshpc-control-h-*`,\n * **有边 / 无边同高**(边框在内部补回)\n * - `block`:撑满父宽\n *\n * 内容轴:`icon`(前置)/ `iconRight`(后置)/ `loading`(前置小圈并自动禁用)。\n * 颜色轴:任一档都可以再用 `color` 传任意 CSS 色值 —— 只覆盖 `--btn-*` 几个变量,\n * 不新增皮肤(皮肤仍只在 `controls-css.ts` 里)。\n *\n * `IconButton` 是纯图标钮:`plain`(默认无底无边,hover 起灰底)/ `outline`(描边)/ `danger`(红)。\n * 兼容别名:`danger-ink` 仍是 `danger-outline` 的旧类名,可直接挂 className。\n *\n * ⚠️ 不许在任何使用点就地写按钮样式;要多一档外观 ⇒ 改基础层(一处改全站生效)。\n */\nimport { ensureControls } from './css.js';\nimport { createElement as h } from 'react';\n/** 实心档(color 参数按「底色」处理;其余档按「字色 + 描边色」处理)。 */\nconst SOLID_VARIANTS = ['primary', 'secondary', 'danger', 'success', 'warning', 'info'];\n/** 把自定义颜色翻译成 5 个局部变量(只覆盖 token,不新增皮肤)。 */\nfunction colorVars(variant, color) {\n if (color === undefined || color === '')\n return undefined;\n if (SOLID_VARIANTS.includes(variant)) {\n return {\n '--btn-bg': color,\n // 亮色主题下 --dshpc-fg 是黑 ⇒ 压深;暗色下是白 ⇒ 提亮。两边都能明确看出变化。\n '--btn-bg-hover': `color-mix(in srgb, ${color} 82%, var(--dshpc-fg))`,\n '--btn-bg-active': `color-mix(in srgb, ${color} 70%, var(--dshpc-fg))`,\n };\n }\n return {\n '--btn-fg': color,\n '--btn-fg-hover': color,\n '--btn-border': color,\n '--btn-bg-hover': `color-mix(in srgb, ${color} 12%, transparent)`,\n '--btn-bg-active': `color-mix(in srgb, ${color} 18%, transparent)`,\n };\n}\n/** 组装按钮 class(结构一套 + 轴类)。 */\nfunction buttonClass(variant, size, block, hasIcon, extra) {\n return `dshpc-btn dshpc-btn--${variant} dshpc-btn--${size}`\n + `${block ? ' dshpc-btn--block' : ''}`\n // 前置图标标记:block 时靠它把文字拉回视觉中心(见 controls-css 的 --icon-start 规则)\n + `${hasIcon ? ' dshpc-btn--icon-start' : ''}`\n + `${extra !== undefined && extra !== '' ? ` ${extra}` : ''}`;\n}\n/**\n * 渲染一个「图标 + 文案」按钮。\n *\n * @param props 见 {@link ButtonProps}。\n * @returns 按钮元素。\n */\nexport function Button(props) {\n ensureControls();\n const { variant = 'outline', size = 'lg', icon, iconRight, color, loading = false, block = false, className, style, children, ...rest } = props;\n const attrs = {\n ...rest,\n type: rest.type ?? 'button',\n disabled: rest.disabled === true || loading,\n className: buttonClass(variant, size, block, icon !== undefined && icon !== null && !loading, className),\n style: { ...colorVars(variant, color), ...style },\n };\n return h('button', attrs, loading\n // 转圈用 SVG 矢量弧,不用 border 画环:1.5px 的次像素边框在 12px 圆上会被抗锯齿拉毛,\n // 看着像圆角方(实测 computed radius 确实是 999px,不是被覆盖 —— 是渲染质量问题)。\n ? h('svg', {\n className: 'dshpc-btn__spinner',\n viewBox: '0 0 12 12',\n width: 12,\n height: 12,\n 'aria-hidden': true,\n }, h('circle', {\n cx: 6, cy: 6, r: 4.75, fill: 'none',\n stroke: 'currentColor', strokeWidth: 1.5, strokeLinecap: 'round',\n // 周长 ≈ 29.85,画 22 的弧 + 足够长的空缺 ⇒ 一个约 270° 的开口环\n strokeDasharray: '22 30',\n }))\n : icon !== undefined && icon !== null\n ? h('span', { className: 'dshpc-btn__icon' }, icon)\n : null, children, iconRight !== undefined && iconRight !== null\n ? h('span', { className: 'dshpc-btn__icon-end' }, iconRight)\n : null);\n}\n/**\n * 渲染一个纯图标按钮。\n *\n * @param props 见 {@link IconButtonProps}。\n * @returns 图标按钮元素。\n */\nexport function IconButton(props) {\n ensureControls();\n const { variant = 'plain', size = 'lg', icon, label, className, style, ...rest } = props;\n const attrs = {\n ...rest,\n type: rest.type ?? 'button',\n title: rest.title ?? label,\n 'aria-label': rest['aria-label'] ?? label,\n className: `dshpc-iconbtn dshpc-iconbtn--${variant} dshpc-iconbtn--${size}${className !== undefined && className !== '' ? ` ${className}` : ''}`,\n style,\n };\n return h('button', attrs, icon);\n}\n//# sourceMappingURL=Button.js.map","import { createElement as h } from 'react';\nimport { ensureControls } from './css.js';\nimport { t } from '../utils/i18n.js';\n/** 色条档位(映射到 design 的 token,不新增 token;也接受任意 CSS 颜色值)。 */\nexport const CARD_ACCENTS = ['business', 'success', 'warning', 'danger', 'neutral'];\n/**\n * 内部共享壳:两个公开组件(`Card` / `StripCard`)只是 `kind` 不同——\n * 一个组件一种外观,import 即表明用的是哪种。\n *\n * 两种外观的头部都是**整体垂直居中**(`align-items:center`):调用方在 `action` 里\n * 裸放一个元素(按钮 / 文字 / 图标)即垂直居中,不用自己套容器;框内一行两行、\n * 右侧放什么、悬停浮出的按钮,都由调用方在框内自定——外壳只提供框与居中。\n */\nfunction CardShell(kind, props) {\n ensureControls();\n const tt = props.translate ?? t;\n const accent = props.accent ?? 'business';\n const isPreset = CARD_ACCENTS.includes(accent);\n const classes = [\n 'dshpc-card',\n kind === 'strip' ? 'dshpc-card--strip' : 'dshpc-card--bordered',\n isPreset ? `dshpc-card--${accent}` : '',\n props.className ?? '',\n ]\n .filter((s) => s !== '')\n .join(' ');\n // 自定义色走 CSS 变量(档位则用 class 里的 token)\n const style = isPreset\n ? props.style\n : { ...props.style, ['--card-accent']: accent };\n return h('div', { className: classes, style }, h('div', { className: 'dshpc-card__head' }, \n // 色条是头部第一个子元素:strip 外观 = 绝对定位 4px 通高贴左缘;bordered 外观 = 行内 6px 圆角短条(高度跟随内容,最小一行,左移 3px)。\n h('span', { className: 'dshpc-card__bar', 'aria-hidden': true }), h('div', { className: 'dshpc-card__main' }, props.children ?? null), props.action === undefined && props.onToggle === undefined\n ? null\n : h('div', { className: 'dshpc-card__side' }, props.action ?? null, props.onToggle === undefined\n ? null\n : h('button', {\n type: 'button',\n className: 'dshpc-card__toggle',\n 'aria-label': tt('cardToggle'),\n 'aria-expanded': props.expanded === true,\n onClick: props.onToggle,\n }, h('span', { className: props.expanded === true ? 'dshpc-card__caret is-open' : 'dshpc-card__caret' }, '▾')))), props.panel === undefined || props.expanded !== true\n ? null\n : h('div', { className: 'dshpc-card__panel' }, props.panel));\n}\n/**\n * 卡片(框式):surface 底 + 1px 边框 + 圆角,左缘行内 6px 圆角短条(高度随内容)。\n * 头部整体垂直居中;悬停浮出的按钮、一行两行由调用方在框内自定。\n *\n * ```tsx\n * h(Card, {\n * accent: 'warning',\n * action: h(Button, { size: 'sm', variant: 'ghost' }, '跳过'),\n * }, h('div', null, '标题 + 内容'))\n * ```\n */\nexport function Card(props) {\n return CardShell('bordered', props);\n}\n/**\n * 条带卡片(浅底式):同色系浅底 + 1px 不可见占位边框 + 方角 + 左缘 4px 通高方角色条(贴左缘)。\n * 与 `Card` 同一份 props,头部同样整体垂直居中。\n *\n * ```tsx\n * h(StripCard, {\n * accent: 'success',\n * expanded: open, onToggle: () => setOpen(!open),\n * panel: h('div', null, '展开详情'),\n * }, h('div', null, '标题 + 元信息'))\n * ```\n */\nexport function StripCard(props) {\n return CardShell('strip', props);\n}\n//# sourceMappingURL=Card.js.map","import { createElement as h } from 'react';\nimport { ensureControls } from './css.js';\n/** 小标签(neutral 用现成的 `--dshpc-chip-bg`;传 `onClick` 才是可点的)。 */\nexport function Chip(props) {\n ensureControls();\n const clickable = props.onClick !== undefined;\n const tone = props.tone ?? 'neutral';\n const size = props.size ?? 'sm';\n return h(clickable ? 'button' : 'span', {\n type: clickable ? 'button' : undefined,\n className: `dshpc-chip`\n + `${tone !== 'neutral' ? ` dshpc-chip--${tone}` : ''}`\n + `${size !== 'sm' ? ` dshpc-chip--${size}` : ''}`\n + `${clickable ? ' dshpc-chip--clickable' : ''}`\n + `${props.className === undefined ? '' : ` ${props.className}`}`,\n onClick: props.onClick,\n }, props.children ?? null);\n}\n//# sourceMappingURL=Chip.js.map","/**\n * 分段控件(滑动块)—— **全站唯一实现**(L2 组件皮肤,P1)\n *\n * 它是「同一份结构 + 两个受控轴」的样板:\n * - `size`:`sm`(24) / `md`(28) / `lg`(32) —— **离散三档**,调用点**不许**自己写高度\n * (真不够用才允许在调用点本地覆盖 `--dshpc-control-h-*`,属例外而非常态);\n * - `bordered`(默认 false):最外再包一圈 1px 描边;总高与无框版逐像素一致\n * (border 由 padding 抵消),两种模式整行混排不跳高。\n *\n * 外观只有一套(灰底轨道 + 白色选中片,阴影来自宿主 elevation token)。\n * 2026-10-26 删掉 `variant` 轴(原 default / inset 两档在 CSS 里只差 1px 内距,\n * 且 default 比 `size` 承诺矮 2px,下游照 demo 对图时反复查不出原因 —— 见 docs/design/style.md)。\n *\n * 用法:\n * // 单选\n * h(Segmented<'a' | 'b'>, { value: v, size: 'md', items: [{ value: 'a', label: '甲' }], onChange: setV })\n * // 多选(如星期)\n * h(Segmented<'1' | '2'>, { multiple: true, value: vs, items: [...], onChange: setVs })\n *\n * ⚠️ 不许在任何使用点就地写分段样式;要多一档高度 / 多一个外观 ⇒ 走\n * docs/design/ui-style-guide.md §五 的流程(改基础层,一处改全站生效)。\n */\nimport { ensureControls } from './css.js';\nimport { createElement as h, useCallback, useLayoutEffect, useRef, useState, } from 'react';\nimport { getTooltipRenderer } from './tooltip.js';\n/**\n * 渲染一个分段控件(单选 / 多选同体)。\n *\n * @param props 见 {@link SegmentedProps}。\n * @returns 分段控件元素。\n */\nexport function Segmented(props) {\n // 幂等:token 层 + 控件皮肤(首次渲染时挂上,之后是空转)\n ensureControls();\n ensureControls();\n const size = props.size ?? 'lg';\n const multiple = props.multiple === true;\n const value = props.value;\n const onChange = props.onChange;\n // 单选:选中底由一块共用「滑动块」承担,点选后从旧段滑到新段(多选每段各自着色,没有唯一滑块可滑)。\n const sliding = !multiple && props.items.length > 1;\n const rootRef = useRef(null);\n const [thumb, setThumb] = useState(null);\n // 量选中段的位置:容器 width 由内容决定,段宽又随文案 / 角标变,只能读一次布局。\n const measure = useCallback(() => {\n const sel = rootRef.current?.querySelector('.dshpc-seg__item[aria-pressed=\"true\"]');\n if (sel === undefined || sel === null) {\n setThumb(null);\n return;\n }\n const next = { left: sel.offsetLeft, top: sel.offsetTop, width: sel.offsetWidth, height: sel.offsetHeight };\n // 尺寸没变就不 set,免得 ResizeObserver 与渲染互相打转。\n setThumb((cur) => cur !== null && cur.left === next.left && cur.top === next.top && cur.width === next.width && cur.height === next.height\n ? cur\n : next);\n }, []);\n useLayoutEffect(() => {\n if (!sliding) {\n setThumb(null);\n return;\n }\n measure();\n const root = rootRef.current;\n // 容器被布局改宽(block / 换行 / webfont 到位)时重测;首帧 thumb 是插入的新元素,不触发过渡。\n if (root === null || typeof ResizeObserver === 'undefined')\n return;\n const ro = new ResizeObserver(measure);\n ro.observe(root);\n return () => ro.disconnect();\n }, [sliding, measure, value, size, props.items, props.bordered, props.block]);\n // 核心 Tooltip 渲染器(宿主启动注入官方 Tooltip;未注入则段级提示降级为无)。\n const renderer = getTooltipRenderer();\n return h('div', {\n role: 'group',\n 'aria-label': props.label,\n id: props.id,\n ref: rootRef,\n // 结构一套、皮肤只在 controls-css 里;此处只拼「轴」类名,不写任何颜色 / 尺寸字面值。\n className: `dshpc-seg dshpc-seg--${size}${sliding ? ' dshpc-seg--slide' : ''}${props.block === true ? ' dshpc-seg--block' : ''}${props.bordered === true ? ' dshpc-seg--bordered' : ''}${props.className !== undefined ? ` ${props.className}` : ''}`,\n style: props.style,\n }, [\n sliding && thumb !== null\n ? h('span', {\n key: '__thumb__',\n className: 'dshpc-seg__thumb',\n 'aria-hidden': true,\n style: {\n left: `${String(thumb.left)}px`,\n top: `${String(thumb.top)}px`,\n width: `${String(thumb.width)}px`,\n height: `${String(thumb.height)}px`,\n },\n })\n : null,\n ...props.items.map(item => {\n const on = multiple ? value.includes(item.value) : value === item.value;\n const disabled = item.disabled === true || props.disabled === true;\n const handle = () => {\n if (disabled)\n return;\n if (multiple) {\n const arr = value;\n const next = arr.includes(item.value) ? arr.filter(v => v !== item.value) : [...arr, item.value];\n onChange(next);\n }\n else {\n ;\n onChange(item.value);\n }\n };\n const itemButton = h('button', {\n key: item.value,\n type: 'button',\n className: 'dshpc-seg__item',\n // 选中态用 aria-pressed 表达 ⇒ 读屏可读,皮肤也只认这一个选择器\n 'aria-pressed': on,\n disabled,\n onClick: handle,\n }, item.label, item.count !== undefined && item.count > 0\n ? h('span', { className: 'dshpc-seg__count' }, String(item.count))\n : null, item.badge !== undefined && item.badge > 0\n ? h('span', { className: 'dshpc-seg__badge' }, String(item.badge))\n : null);\n // 段级悬停提示:走注入的官方 Tooltip(与 FieldHint 同一条路),不破坏分段布局。\n if (item.tooltip !== undefined && renderer !== undefined) {\n return renderer({ label: item.tooltip, side: 'top', children: itemButton });\n }\n return itemButton;\n }),\n ]);\n}\n//# sourceMappingURL=Segmented.js.map","/**\n * 输入类控件 —— **全站唯一实现**(L2 组件皮肤,P3)\n *\n * - `Input`:文本输入(size sm 24 / md 28 / lg 32,error 描红);\n * - `PrefixedInput`:前缀 + 文本输入(如路径 / 接口前缀);\n * - `NumberInput`:数字步进(显式 `− / +`,替换原生 `<input type=\"number\">` 的浏览器 spinner,\n * 支持 step / min / max、clamp、Enter 提交、失焦回弹)。\n *\n * 高度一律吃 `--dshpc-control-h-*`;有边 / 无边同高(边框在内部补回)。\n */\nimport { ensureControls } from './css.js';\nimport { createElement as h, useEffect, useState } from 'react';\nimport { IconButton } from './Button.js';\nimport { FieldHint } from './FieldHint.js';\n/**\n * 字段 hint 的统一包法:控件 + 问号提示同一行(间距/对齐收进组件,调用方传个\n * `hint` 字符串就行,不再手动拼排版 —— 用户 2026-10-20 拍板)。\n */\nexport function withHint(control, hint) {\n if (hint === undefined)\n return control;\n return h('span', { className: 'dshpc-fieldwrap' }, control, h(FieldHint, { text: hint }));\n}\nfunction sizeClass(size) {\n return size === 'lg' ? '--lg' : size === 'md' ? '--md' : '--sm';\n}\n/** 文本输入。默认铺满容器(width:100%,与 Textarea 同口径);要定宽由调用方在外面包壳(如 192px 搜索槽)。 */\nexport function Input(props) {\n ensureControls();\n const { value, onChange, placeholder, size = 'lg', error, disabled, type, className, style } = props;\n return withHint(h('input', {\n ref: props.inputRef,\n type: type ?? 'text',\n value,\n placeholder,\n disabled,\n 'aria-label': props['aria-label'],\n title: props.title,\n className: `dshpc-input dshpc-input${sizeClass(size)}${error === true ? ' dshpc-input--error' : ''}${className !== undefined && className !== '' ? ` ${className}` : ''}`,\n style,\n onChange: (event) => { onChange(event.target.value); },\n onKeyDown: props.onKeyDown,\n onBlur: props.onBlur,\n }), props.hint);\n}\n/** 前缀 + 文本输入。 */\nexport function PrefixedInput(props) {\n ensureControls();\n const { prefix, value, onChange, placeholder, size = 'lg', error, disabled, type, className, style } = props;\n return h('div', {\n className: `dshpc-pfx dshpc-pfx${sizeClass(size)}${error === true ? ' dshpc-pfx--error' : ''}${className !== undefined && className !== '' ? ` ${className}` : ''}`,\n style,\n }, h('span', { className: 'dshpc-pfx__label' }, prefix), h('input', {\n type: type ?? 'text',\n value,\n placeholder,\n disabled,\n 'aria-label': props['aria-label'],\n title: props.title,\n className: 'dshpc-pfx__input',\n onChange: (event) => { onChange(event.target.value); },\n }));\n}\n/**\n * 数字步进输入:显式 `− / +` 按钮 + 可输入数字。\n *\n * @param props 见 {@link NumberInputProps}。\n * @returns 数字步进控件。\n */\nexport function NumberInput(props) {\n ensureControls();\n const { value, onChange, min = -Infinity, max = Infinity, step = 1, size = 'lg', inputWidth, disabled, suffix, label, decreaseLabel = '减少', increaseLabel = '增加', className, style, } = props;\n const [text, setText] = useState(String(value));\n // 外部值变化(如切档位重置)时同步回输入框。\n useEffect(() => { setText(String(value)); }, [value]);\n const clamp = (n) => Math.min(max, Math.max(min, n));\n const commit = (raw) => {\n // ⚠️ 空串按「输入无效」回弹,**不能**当成 0(2026-10-08 真机 bug:`Number('') === 0` ⇒\n // 用户按 Delete 把数字删空后失焦,值被 clamp 成 min,看起来就是「按 Delete 不管用」)。\n if (raw.trim() === '') {\n setText(String(value));\n return;\n }\n const n = Number(raw);\n if (!Number.isFinite(n)) {\n setText(String(value));\n return;\n }\n const next = clamp(n);\n setText(String(next));\n if (next !== value)\n onChange(next);\n };\n const bump = (dir) => {\n const base = Number.isFinite(Number(text)) ? Number(text) : value;\n const next = clamp(base + dir * step);\n setText(String(next));\n if (next !== value)\n onChange(next);\n };\n return withHint(h('div', {\n className: `dshpc-num dshpc-num${sizeClass(size)}${disabled === true ? ' dshpc-num--disabled' : ''}${className !== undefined && className !== '' ? ` ${className}` : ''}`,\n style,\n }, h(IconButton, { variant: 'plain', size, icon: '−', label: decreaseLabel, disabled, onClick: () => { bump(-1); } }), \n // 中段(数字 + 后缀)成组居中:消费端把宽度拉大时,「−」钉最左、「+」钉最右、数字组始终居中\n // (用户 2026-10-18:加减号必须在最左 / 最右,宽度由消费端调)。\n h('span', { className: 'dshpc-num__mid' }, h('input', {\n className: 'dshpc-num__input',\n ...(inputWidth === undefined ? {} : { style: { width: `${inputWidth}px` } }),\n value: text,\n disabled,\n inputMode: 'numeric',\n 'aria-label': label,\n onChange: (event) => { setText(event.target.value); },\n onBlur: () => { commit(text); },\n onKeyDown: (event) => { if (event.key === 'Enter')\n commit(text); },\n }), suffix !== undefined ? h('span', { className: 'dshpc-num__suffix' }, suffix) : null), h(IconButton, { variant: 'plain', size, icon: '+', label: increaseLabel, disabled, onClick: () => { bump(1); } })), props.hint);\n}\n/**\n * 下拉锚点的统一样式(**全站唯一一份**):`SelectField` 与 `TaskPicker` 共用 —— 两者是同一类锚点,\n * 不许各抄一份(2026-10-04 评审:TaskPicker 曾抄第二/第三份,观感会持续漂移)。\n */\nexport const FIELD_ANCHOR_STYLE = {\n display: 'inline-flex', alignItems: 'center', gap: '6px', height: 'var(--dshpc-control-h-lg)', boxSizing: 'border-box',\n minWidth: 0, maxWidth: '100%', padding: '0 var(--dshpc-space-2)',\n border: '0.5px solid var(--dshpc-border-heavy)', borderRadius: 'var(--dshpc-radius-md)', background: 'var(--dshpc-surface-1)',\n color: 'var(--dshpc-fg)', font: 'inherit', fontSize: 'var(--dshpc-font-md)', lineHeight: 'var(--dshpc-line-md)', cursor: 'pointer',\n transition: 'background var(--dshpc-dur-fast) var(--dshpc-ease), color var(--dshpc-dur-fast) var(--dshpc-ease), border-color var(--dshpc-dur-fast) var(--dshpc-ease)',\n};\n/** 下拉锚点里那行文字(省略号三件套收敛到 `.dshpc-ellipsis`,见 ui-style-guide §三 待抽象 #1)。 */\nexport const FIELD_LABEL_STYLE = {\n flex: '1 1 auto', minWidth: 0, textAlign: 'left',\n};\n/** 尺寸档 → 锚点几何(高度 / 字号 / 行高 / 图标 / 间距)。**翻译只此一处**,下拉类控件共用。 */\nexport function fieldMetricsOf(size) {\n return {\n height: size === 'sm' ? 'var(--dshpc-control-h-sm)' : size === 'md' ? 'var(--dshpc-control-h-md)' : 'var(--dshpc-control-h-lg)',\n font: size === 'sm' ? 'var(--dshpc-font-sm)' : 'var(--dshpc-font-md)',\n line: size === 'sm' ? 'var(--dshpc-line-sm)' : 'var(--dshpc-line-md)',\n icon: size === 'sm' ? 14 : 16,\n gap: size === 'sm' ? 'var(--dshpc-space-1)' : '6px',\n };\n}\n//# sourceMappingURL=Field.js.map","/**\n * 列表视图的筛选 / 分区 / 排序(**唯一**实现,纯函数、不碰网络):页面只渲染,不各写一份过滤。\n * 定稿见 docs/design/features/board-home.md §二.3:两区结构(我的待办平铺 / 按工作区分组),\n * 已结案**不在首页**(去统计 tab)。\n *\n * 单独成文件是为了能被冒烟直测(store.ts 引 api.ts,Node 剥类型解析不了无扩展名相对导入)。\n */\n\nimport type { Query } from \"./store\";\nimport type { BoardPayload, BoardTask, HistoryRecord } from \"./types\";\n\n/** 列表行:在办与已结案两套形状,行件按 kind 分支(不做「统一成一个假结构」的归一化)。 */\nexport type Row =\n\t| { kind: \"task\"; key: string; task: BoardTask; mine: boolean }\n\t| { kind: \"closed\"; key: string; record: HistoryRecord };\n\n/**\n * 界面上显示人名的**唯一**口径:显示名(`owner_name` / `creator_name`)优先,\n * 旧数据 / 名册里没名字才退回 uuid。**只用于显示与搜索** —— 归属判定一律比 uuid(见 `isMine`)。\n */\nexport function displayName(\n\tname: string | null | undefined,\n\tuuid: string | null | undefined,\n): string {\n\tconst label = (name ?? \"\").trim();\n\treturn label !== \"\" ? label : (uuid ?? \"\").trim();\n}\n\n/** 一个工作区分组(计数口径:待认领 / 进行中 / 积压 / 逾期 / 停滞 / 总,供「全部待办」段头统计)。 */\nexport interface WorkspaceGroup {\n\treadonly workspaceId: string;\n\treadonly title: string;\n\treadonly doingCount: number;\n\treadonly overdueCount: number;\n\treadonly staleCount: number;\n\treadonly backlogCount: number;\n\treadonly openCount: number;\n\treadonly total: number;\n\treadonly rows: readonly Row[];\n}\n\n/** 两区视图:第一区我的待办 + 第二区按工作区分组(第二区含全部任务,会与第一区重叠——用户 2026-10-18 要「全部待办」)。 */\nexport interface BoardView {\n\treadonly mine: readonly Row[];\n\treadonly groups: readonly WorkspaceGroup[];\n\t/** 第二区(全部待办)任务数。 */\n\treadonly total: number;\n\t/** 第二区全量计数(**不受状态过滤影响**,供 segmented 角标;异常标记相互独立;含我的)。 */\n\treadonly allCounts: {\n\t\treadonly total: number;\n\t\treadonly doing: number;\n\t\treadonly open: number;\n\t\treadonly overdue: number;\n\t\treadonly stale: number;\n\t\treadonly backlog: number;\n\t};\n}\n\n/** 关键字命中(标题 / 任务号 / 人 / 分类 / 标签;已结案另含「完成了什么」)。 */\nfunction hitKeyword(\n\tkeyword: string,\n\tparts: readonly (string | null | undefined)[],\n): boolean {\n\tconst needle = keyword.trim().toLowerCase();\n\tif (needle === \"\") return true;\n\treturn parts.some((part) => part?.toLowerCase().includes(needle) === true);\n}\n\n/** uuid 比较:两边都 trim + 小写(身份键不分大小写,与脚本 `normalize` 同口径)。 */\nexport function sameUuid(\n\ta: string | null | undefined,\n\tb: string | null | undefined,\n): boolean {\n\tconst left = (a ?? \"\").trim().toLowerCase();\n\tconst right = (b ?? \"\").trim().toLowerCase();\n\treturn left !== \"\" && left === right;\n}\n\n/** 「我的」判定:owner = 本机身份 uuid,且状态是进行中(blocked 是旧数据,照收;与 host 同口径)。 */\nexport function isMine(task: BoardTask, board: BoardPayload | null): boolean {\n\tif (board === null) return false;\n\tconst identity = board.identities[task.workspace.id] ?? null;\n\tif (identity === null || identity === \"\") return false;\n\treturn (\n\t\tsameUuid(task.owner, identity) &&\n\t\t(task.status === \"doing\" || task.status === \"blocked\")\n\t);\n}\n\n/**\n * 任务动作权限(**唯一**判定,两区共用——用户 2026-10-18:不许各判各的)。\n * 传任务 + 快照进去,返回「能做哪些动作」;界面只按返回值画按钮,不再自己判断是不是我的。\n * ⇒ 第二区(全部待办)里**我的**任务也能继续 / 结束 / 释放,跟第一区一模一样。\n */\nexport interface TaskActions {\n\t/** 查看详情(两区、所有任务都有)。 */\n\treadonly view: boolean;\n\t/** 认领:只有**没人认领**(待认领)的任务能认领。 */\n\treadonly claim: boolean;\n\treadonly resume: boolean;\n\treadonly finish: boolean;\n\treadonly release: boolean;\n}\n\nexport function resolveActions(\n\ttask: BoardTask,\n\tboard: BoardPayload | null,\n): TaskActions {\n\tconst mine = isMine(task, board);\n\treturn {\n\t\tview: true,\n\t\tclaim: !mine && task.status === \"open\",\n\t\tresume: mine,\n\t\tfinish: mine,\n\t\trelease: mine,\n\t};\n}\n\n/** 已结案行(统计 tab):只有查看,没有在办动作。 */\nexport const CLOSED_ACTIONS: TaskActions = {\n\tview: true,\n\tclaim: false,\n\tresume: false,\n\tfinish: false,\n\trelease: false,\n};\n\n/** 状态档命中(积压 / 逾期 / 停滞由 host 标记,前端不判阈值)——只作用于第二区。 */\nfunction statusHit(task: BoardTask, status: Query[\"status\"]): boolean {\n\tif (status === \"all\") return true;\n\tif (status === \"active\")\n\t\treturn task.status === \"doing\" || task.status === \"blocked\";\n\tif (status === \"open\") return task.status === \"open\";\n\tif (status === \"backlog\") return task.backlog === true;\n\tif (status === \"overdue\") return task.overdue === true;\n\treturn task.stale === true;\n}\n\n/** 组内排序:别人的进行中在前、待认领在后;各自按创建 / 开始时间倒序。 */\nfunction inGroupOrder(a: Row, b: Row): number {\n\tif (a.kind !== \"task\" || b.kind !== \"task\") return 0;\n\tconst rank = (task: BoardTask): number => (task.status === \"open\" ? 1 : 0);\n\tif (rank(a.task) !== rank(b.task)) return rank(a.task) - rank(b.task);\n\treturn String(b.task.created ?? b.task.started ?? \"\").localeCompare(\n\t\tString(a.task.created ?? a.task.started ?? \"\"),\n\t);\n}\n\n/**\n * 当前筛选下的两区视图(用户 2026-10-18 调整):\n * - 第一区「我的待办」= 我名下 doing/blocked,吃工作区下拉 + 标题搜索,按创建时间倒序;\n * - 第二区「全部待办」= **所有**在办任务按工作区分组(含我的——用户明确不要过滤掉自己),\n * 吃**状态档**(segmented)+ **标题 / 执行人搜索**(othersKeyword);一个整表(外框连着)。\n * ⇒ 我的任务会同时出现在两个区,这是预期(顶部快看 / 底部全量)。\n */\nexport function selectView(current: {\n\tboard: BoardPayload | null;\n\tquery: Query;\n}): BoardView {\n\tconst { board, query } = current;\n\tif (board === null) {\n\t\treturn {\n\t\t\tmine: [],\n\t\t\tgroups: [],\n\t\t\ttotal: 0,\n\t\t\tallCounts: {\n\t\t\t\ttotal: 0,\n\t\t\t\tdoing: 0,\n\t\t\t\topen: 0,\n\t\t\t\toverdue: 0,\n\t\t\t\tstale: 0,\n\t\t\t\tbacklog: 0,\n\t\t\t},\n\t\t};\n\t}\n\tconst allTasks = board.tasks;\n\tconst allCounts = {\n\t\ttotal: allTasks.length,\n\t\tdoing: allTasks.filter((task) => task.status === \"doing\").length,\n\t\topen: allTasks.filter((task) => task.status === \"open\").length,\n\t\toverdue: allTasks.filter((task) => task.overdue === true).length,\n\t\tstale: allTasks.filter((task) => task.stale === true).length,\n\t\tbacklog: allTasks.filter((task) => task.backlog === true).length,\n\t};\n\tconst mineRows: Row[] = board.tasks\n\t\t.filter((task) => isMine(task, board))\n\t\t.filter(\n\t\t\t(task) => query.workspace === \"\" || task.workspace.id === query.workspace,\n\t\t)\n\t\t.filter((task) =>\n\t\t\thitKeyword(query.keyword, [\n\t\t\t\ttask.title,\n\t\t\t\ttask.id,\n\t\t\t\t// 搜的是**人名**:uuid 是机器键,人不会拿它搜\n\t\t\t\tdisplayName(task.owner_name, task.owner),\n\t\t\t\tdisplayName(task.creator_name, task.creator),\n\t\t\t\ttask.category,\n\t\t\t\t...(task.tags ?? []),\n\t\t\t]),\n\t\t)\n\t\t.sort((a, b) =>\n\t\t\tString(b.created ?? b.started ?? \"\").localeCompare(\n\t\t\t\tString(a.created ?? a.started ?? \"\"),\n\t\t\t),\n\t\t)\n\t\t.map(\n\t\t\t(task): Row => ({\n\t\t\t\tkind: \"task\",\n\t\t\t\tkey: `${task.workspace.id}:${task.id}`,\n\t\t\t\ttask,\n\t\t\t\tmine: true,\n\t\t\t}),\n\t\t);\n\tconst rest =\n\t\tquery.scope === \"mine\"\n\t\t\t? []\n\t\t\t: board.tasks\n\t\t\t\t\t.filter((task) => statusHit(task, query.status))\n\t\t\t\t\t.filter((task) =>\n\t\t\t\t\t\thitKeyword(query.othersKeyword, [\n\t\t\t\t\t\t\ttask.title,\n\t\t\t\t\t\t\tdisplayName(task.owner_name, task.owner),\n\t\t\t\t\t\t]),\n\t\t\t\t\t);\n\tconst byWorkspace = new Map<string, { title: string; rows: Row[] }>();\n\tfor (const task of rest) {\n\t\tconst entry = byWorkspace.get(task.workspace.id) ?? {\n\t\t\ttitle: task.workspace.title,\n\t\t\trows: [],\n\t\t};\n\t\t// mine 必须说实话(第二区现在含全部任务,连我的也在里面):按钮权限由 resolveActions 判,\n\t\t// 但这一位同样是数据面,不许一律写 false。\n\t\tentry.rows.push({\n\t\t\tkind: \"task\",\n\t\t\tkey: `${task.workspace.id}:${task.id}`,\n\t\t\ttask,\n\t\t\tmine: isMine(task, board),\n\t\t});\n\t\tbyWorkspace.set(task.workspace.id, entry);\n\t}\n\tconst groups: WorkspaceGroup[] = [...byWorkspace.entries()]\n\t\t.map(([workspaceId, entry]) => ({\n\t\t\tworkspaceId,\n\t\t\ttitle: entry.title,\n\t\t\tdoingCount: entry.rows.filter(\n\t\t\t\t(row) => row.kind === \"task\" && row.task.status === \"doing\",\n\t\t\t).length,\n\t\t\toverdueCount: entry.rows.filter(\n\t\t\t\t(row) => row.kind === \"task\" && row.task.overdue === true,\n\t\t\t).length,\n\t\t\tstaleCount: entry.rows.filter(\n\t\t\t\t(row) => row.kind === \"task\" && row.task.stale === true,\n\t\t\t).length,\n\t\t\tbacklogCount: entry.rows.filter(\n\t\t\t\t(row) => row.kind === \"task\" && row.task.backlog === true,\n\t\t\t).length,\n\t\t\topenCount: entry.rows.filter(\n\t\t\t\t(row) => row.kind === \"task\" && row.task.status === \"open\",\n\t\t\t).length,\n\t\t\ttotal: entry.rows.length,\n\t\t\trows: entry.rows.sort(inGroupOrder),\n\t\t}))\n\t\t.sort((a, b) => a.title.localeCompare(b.title, \"zh-Hans-CN\"));\n\treturn {\n\t\tmine: mineRows,\n\t\tgroups,\n\t\ttotal: groups.reduce((sum, group) => sum + group.rows.length, 0),\n\t\tallCounts,\n\t};\n}\n\n/**\n * 已结案列表(统计 tab 用;首页不渲染已结案 ⇒ 这里只留数据面,供后续统计 tab 复用同一套筛选口径)。\n */\nexport function selectClosed(current: {\n\thistory: readonly HistoryRecord[];\n\tquery: Query;\n}): Row[] {\n\treturn current.history\n\t\t.filter((record) =>\n\t\t\thitKeyword(current.query.keyword, [\n\t\t\t\trecord.summary,\n\t\t\t\trecord.workpackage,\n\t\t\t\tdisplayName(record.owner_name, record.owner),\n\t\t\t\trecord.category,\n\t\t\t\t...(record.tags ?? []),\n\t\t\t]),\n\t\t)\n\t\t.map((record, index) => ({\n\t\t\tkind: \"closed\",\n\t\t\tkey: `${record.src ?? \"\"}:${record.time ?? \"\"}:${index}`,\n\t\t\trecord,\n\t\t}));\n}\n","/**\n * 数据面取数**单源**:所有 client → host 的 HTTP 都在这里,页面不许各写一份 fetch。\n *\n * 纪律:只做传输与形状校验,不造兜底假值(DSH 插件规则「数据真实」)——\n * 失败就抛,由调用方显示错误态;返回什么渲染什么。\n *\n * ⚠️ 必须带超时且 abort 要带 reason:一次挂起的请求会让面板永久停在「读取中」,\n * 而不带 reason 时浏览器把 error.message 填成「signal is aborted without reason」,\n * 看不出是超时(姊妹仓 2026-10-07 真机教训)。\n */\nimport type {\n\tBoardPayload,\n\tCloseHandoff,\n\tFilterOptions,\n\tHistoryRecord,\n\tTaskDetail,\n\tTrendPayload,\n} from \"./types\";\n\n/** host 路由前缀(全仓唯一;与 host/routes.ts 的 API_PREFIX 对应)。 */\nexport const API_PREFIX = \"api/task-ledger\";\n\nconst DEFAULT_TIMEOUT_MS = 8_000;\n/** 趋势端点读 history,比快路径慢一个量级(20 万条实测 4s+),超时单给。 */\nconst TREND_TIMEOUT_MS = 30_000;\n\n/**\n * 错误响应榨人话:host 路由(routes.ts)发的是 `{ error: \"...\" }`,那里的话是**能直接上界面的**\n * (带工作区名、python3 起不来之类的原文)。不带它界面上只剩「HTTP 500」,等于没报错。\n */\nexport function httpErrorMessage(status: number, body: string): string {\n\ttry {\n\t\tconst parsed = JSON.parse(body) as { error?: unknown };\n\t\tif (typeof parsed.error === \"string\" && parsed.error !== \"\")\n\t\t\treturn `HTTP ${status}:${parsed.error}`;\n\t} catch {\n\t\t/* 不是 JSON:走原文 */\n\t}\n\tconst text = body.trim().slice(0, 200);\n\treturn text === \"\"\n\t\t? `HTTP ${String(status)}`\n\t\t: `HTTP ${String(status)}:${text}`;\n}\n\n/** 带超时的 JSON 取数(相对路径,同源)。 */\nexport async function fetchJson<T>(\n\tpath: string,\n\tinit: RequestInit = {},\n\ttimeoutMs = DEFAULT_TIMEOUT_MS,\n): Promise<T> {\n\tconst controller = new AbortController();\n\tconst timer = setTimeout(() => {\n\t\tcontroller.abort(\n\t\t\tnew DOMException(`请求超时(${timeoutMs}ms 未响应)`, \"TimeoutError\"),\n\t\t);\n\t}, timeoutMs);\n\ttry {\n\t\tconst res = await fetch(`${API_PREFIX}${path}`, {\n\t\t\t...init,\n\t\t\tsignal: controller.signal,\n\t\t\tcache: \"no-store\",\n\t\t});\n\t\tif (!res.ok)\n\t\t\tthrow new Error(\n\t\t\t\thttpErrorMessage(res.status, await res.text().catch(() => \"\")),\n\t\t\t);\n\t\treturn (await res.json()) as T;\n\t} finally {\n\t\tclearTimeout(timer);\n\t}\n}\n\n/**\n * 首页快照(快路径:在办全量 + 统计 + 各工作区身份;**不含趋势**)。\n * `fresh` = 让 host 先清 1.5s 读缓存再算(手动刷新 / 首读都要最新,不吃上一屏的缓存)。\n */\nexport function fetchBoardSnapshot(\n\topts: { fresh?: boolean } = {},\n): Promise<BoardPayload> {\n\treturn fetchJson<BoardPayload>(`/board/snapshot${freshSuffix(opts)}`);\n}\n\n/**\n * 趋势(慢路径:近 8 周 + 四个自然周期,host 侧要读 history)。\n * 超时给得比默认宽:历史量大时读得久(实测 20 万条量级 4s+);\n * 旧宿主没有该端点 ⇒ 404,直接抛给调用方兜底,不阻塞列表。\n */\nexport function fetchTrend(\n\topts: { fresh?: boolean } = {},\n): Promise<TrendPayload> {\n\treturn fetchJson<TrendPayload>(\n\t\t`/board/trend${freshSuffix(opts)}`,\n\t\t{},\n\t\tTREND_TIMEOUT_MS,\n\t);\n}\n\n/** `?fresh=1` 只在真要最新值时带;不带就吃 host 的 1.5s 缓存。 */\nfunction freshSuffix(opts: { fresh?: boolean }): string {\n\treturn opts.fresh === true ? \"?fresh=1\" : \"\";\n}\n\n/** 已结案列表(服务端按窗口 / 标签 / 分页过滤)。 */\nexport function fetchHistory(params: {\n\tsince?: string;\n\tuntil?: string;\n\ttag?: string;\n\tlimit?: number;\n}): Promise<HistoryRecord[]> {\n\tconst query = new URLSearchParams();\n\tif (params.since !== undefined) query.set(\"since\", params.since);\n\tif (params.until !== undefined) query.set(\"until\", params.until);\n\tif (params.tag !== undefined && params.tag !== \"\")\n\t\tquery.set(\"tag\", params.tag);\n\tif (params.limit !== undefined) query.set(\"limit\", String(params.limit));\n\tconst suffix = query.toString();\n\treturn fetchJson<{ records: HistoryRecord[] }>(\n\t\t`/history${suffix === \"\" ? \"\" : `?${suffix}`}`,\n\t).then((body) => body.records ?? []);\n}\n\n/** 单条在办 + 过程文档正文(展开行用)。 */\nexport function fetchTaskDetail(\n\tworkspaceId: string,\n\ttaskId: string,\n): Promise<TaskDetail> {\n\tconst query = new URLSearchParams({ ws: workspaceId, id: taskId });\n\treturn fetchJson<TaskDetail>(`/task?${query.toString()}`);\n}\n\n/** 筛选项候选(在办全量 + 近 13 个月历史的去重 owner / category / tag)。 */\nexport function fetchFilters(): Promise<FilterOptions> {\n\treturn fetchJson<FilterOptions>(\"/filters\");\n}\n\n/**\n * 结束任务:请 host 起一个会话(首条 = 预置提示词 + 用户留言),返回 `sessionId` 供跳转。\n *\n * `message` 是用户在弹框里留的话(可空);`provider` / `model` 成对给 = 用用户选的模型,\n * 都不给 = 用宿主默认模型(只给一半会被 host 400 拒,不做猜测)。\n */\nexport function requestClose(body: {\n\tws: string;\n\tid: string;\n\tmessage: string;\n\tprovider?: string;\n\tmodel?: string;\n}): Promise<CloseHandoff> {\n\treturn fetchJson<CloseHandoff>(\"/close\", {\n\t\tmethod: \"POST\",\n\t\theaders: { \"content-type\": \"application/json\" },\n\t\tbody: JSON.stringify(body),\n\t});\n}\n\n/** 认领 / 释放的写结果;成功后由调用方自行刷新快照(host 已清该工作区读缓存)。 */\nexport interface TaskMutationResult {\n\treadonly ok: true;\n\t/** 写成功但同步(commit / push)没成功时的人话;同步正常时没有这个字段。 */\n\treadonly notice?: string;\n}\n\n/**\n * 认领:点一下即归当前用户(host 直跑脚本,不开会话)。\n * 只有 `open` 且无人认领才允许,忙时 host 回 500 + 人话(脚本原文)。\n */\nexport function requestClaim(body: {\n\tws: string;\n\tid: string;\n}): Promise<TaskMutationResult> {\n\treturn fetchJson<TaskMutationResult>(\"/claim\", {\n\t\tmethod: \"POST\",\n\t\theaders: { \"content-type\": \"application/json\" },\n\t\tbody: JSON.stringify(body),\n\t});\n}\n\n/** 释放:退回待认领(owner 清空),只许当前 owner 本人(host 侧脚本校验)。 */\nexport function requestRelease(body: {\n\tws: string;\n\tid: string;\n}): Promise<TaskMutationResult> {\n\treturn fetchJson<TaskMutationResult>(\"/release\", {\n\t\tmethod: \"POST\",\n\t\theaders: { \"content-type\": \"application/json\" },\n\t\tbody: JSON.stringify(body),\n\t});\n}\n","/**\n * 看板数据仓(client 侧**唯一**取数入口):浮标角标与整页共用同一份快照,\n * 谁先挂载谁触发首读;刷新按钮走同一个 `refresh()`,**不轮询**(2026-10-17 拍板:\n * 后端纯按需,刷新时机归前端 = 打开面板首读 + 手动刷新)。\n *\n * 消费方式:`useSyncExternalStore(boardSubscribe, boardSnapshot)`。\n * ⚠️ `getSnapshot` 必须返回**稳定引用**(每次新建对象会被判定为「一直在变」⇒ 无限重渲染),\n * 故只在真变了时才换 `state` 对象。\n */\nimport { fetchBoardSnapshot, fetchTrend } from \"./api\";\nimport type { BoardPayload, TrendPayload } from \"./types\";\n\n/** 范围:我的 / 全部工作区。 */\nexport type Scope = \"mine\" | \"all\";\n/** 状态档:进行中 = doing;积压 / 逾期 / 停滞 = host 按时间标记的 backlog / overdue / stale。 */\nexport type StatusFilter =\n\t| \"all\"\n\t| \"active\"\n\t| \"open\"\n\t| \"backlog\"\n\t| \"overdue\"\n\t| \"stale\";\n\nexport interface Query {\n\tscope: Scope;\n\t/** 「其他待办」的状态档过滤(segmented)。 */\n\tstatus: StatusFilter;\n\t/** 工作区 id;'' = 全部工作区(只作用于「我的待办」)。 */\n\tworkspace: string;\n\t/** 「我的待办」的标题搜索。 */\n\tkeyword: string;\n\t/** 「其他待办」的搜索(标题 / 执行人)。 */\n\tothersKeyword: string;\n}\n\nexport interface BoardState {\n\tstatus: \"loading\" | \"ready\" | \"error\";\n\tboard: BoardPayload | null;\n\terror: string | null;\n\tquery: Query;\n\t/** 手动刷新在途(按钮转圈 / 禁用)。 */\n\trefreshing: boolean;\n\t/** 趋势(慢路径,`/board/trend`):null = 还没回来 / 旧宿主没有该端点。 */\n\ttrend: TrendPayload | null;\n\t/** 趋势加载态:首屏不阻塞列表,图表区自己显示占位 / 兜底文案。 */\n\ttrendStatus: \"idle\" | \"loading\" | \"ready\" | \"error\";\n\ttrendError: string | null;\n}\n\nconst INITIAL_QUERY: Query = {\n\tscope: \"all\",\n\tstatus: \"all\",\n\tworkspace: \"\",\n\tkeyword: \"\",\n\tothersKeyword: \"\",\n};\n\nlet state: BoardState = {\n\tstatus: \"loading\",\n\tboard: null,\n\terror: null,\n\tquery: INITIAL_QUERY,\n\trefreshing: false,\n\ttrend: null,\n\ttrendStatus: \"idle\",\n\ttrendError: null,\n};\n\nconst listeners = new Set<() => void>();\n/** 首读只触发一次(谁先订阅谁触发),之后一律靠 `refresh()` / `setQuery()`。 */\nlet booted = false;\n/** 在途轮次:迟到的响应按 token 丢弃,避免旧结果盖新结果。 */\nlet runToken = 0;\n\nfunction emit(): void {\n\tfor (const listener of [...listeners]) listener();\n}\n\nfunction set(patch: Partial<BoardState>): void {\n\tstate = { ...state, ...patch };\n\temit();\n}\n\nexport function boardSnapshot(): BoardState {\n\treturn state;\n}\n\nexport function boardSubscribe(listener: () => void): () => void {\n\tlisteners.add(listener);\n\tif (!booted) {\n\t\tbooted = true;\n\t\tvoid refresh();\n\t}\n\treturn () => {\n\t\tlisteners.delete(listener);\n\t};\n}\n\n/**\n * 重读(2026-10-18 拆端点):**两段**——先快路径 `/board/snapshot`(只读在办,首屏立即可渲染),\n * 再慢路径 `/board/trend`(读 history,后台拉;迟到按 token 丢弃,不盖新快照)。\n * 趋势失败(含旧宿主 404)不阻塞列表:trendStatus 置 error,图表区显示兜底文案。\n * 两段都带 `fresh=1`:本函数只由首读与手动刷新触发,都要最新值(host 缓存清两次无害,清是全局的)。\n */\nexport async function refresh(): Promise<void> {\n\tconst token = ++runToken;\n\tset({ refreshing: true });\n\ttry {\n\t\tconst board = await fetchBoardSnapshot({ fresh: true });\n\t\tif (token !== runToken) return;\n\t\tset({\n\t\t\tstatus: \"ready\",\n\t\t\tboard,\n\t\t\terror: null,\n\t\t\ttrendStatus: \"loading\",\n\t\t\ttrendError: null,\n\t\t});\n\t} catch (error) {\n\t\tif (token !== runToken) return;\n\t\tset({\n\t\t\tstatus: \"error\",\n\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t});\n\t\treturn;\n\t} finally {\n\t\tif (token === runToken) set({ refreshing: false });\n\t}\n\ttry {\n\t\tconst trend = await fetchTrend({ fresh: true });\n\t\tif (token !== runToken) return;\n\t\tset({ trend, trendStatus: \"ready\", trendError: null });\n\t} catch (error) {\n\t\tif (token !== runToken) return;\n\t\tset({\n\t\t\ttrend: null,\n\t\t\ttrendStatus: \"error\",\n\t\t\ttrendError: error instanceof Error ? error.message : String(error),\n\t\t});\n\t}\n}\n\n/** 改筛选:全部在浏览器里完成(快照已含全部在办),不发请求。 */\nexport function setQuery(patch: Partial<Query>): void {\n\tset({ query: { ...state.query, ...patch } });\n}\n","/**\n * 客户端时间口径**单源**:补零 / 时刻串(本机时区)。\n * 解析失败按调用方给的兜底返回(不编造时间)。\n *\n * 2026-10-17 改版后首页不再做时间范围过滤(时间只作用于统计卡与趋势图,由 host 聚合)\n * ⇒ 原来的 `rangeToDates` / `withinRange` / `RangeKey` 一并删除;统计 tab 要做时间筛选时\n * 按当时口径在此重建,别处不许再写一份。\n */\nexport function pad2(value: number | string): string {\n\treturn String(value).padStart(2, \"0\");\n}\n\n/** ISO → `YYYY-MM-DD HH:mm`(`seconds: true` 时补 `:ss`);解析失败返回 `fallback`(缺省原串)。 */\nexport function formatDateTime(\n\tiso: string,\n\topts?: { seconds?: boolean; fallback?: string },\n): string {\n\tconst ms = Date.parse(iso);\n\tif (Number.isNaN(ms)) return opts?.fallback ?? iso;\n\tconst d = new Date(ms);\n\tconst base = `${d.getFullYear()}-${pad2(d.getMonth() + 1)}-${pad2(d.getDate())} ${pad2(d.getHours())}:${pad2(d.getMinutes())}`;\n\treturn opts?.seconds === true ? `${base}:${pad2(d.getSeconds())}` : base;\n}\n","/**\n * 语义 token 层:`--dtl-*`(dtl = dsh-task-ledger)。\n *\n * 规矩(docs/design/ui-style.md §三,2026-10-17 对齐 dispatch 表后收严):\n * - **只有本文件定义 `--dtl-*`**;其它文件一律 `var(--dtl-*)` 消费,不许直接写 `var(--dsw-*)`;\n * - 每个 token 都带兜底值 ⇒ 宿主升级换名时不炸(最坏退到兜底色,不会白屏);\n * - 明暗差异只写在本文件末尾的 `body[data-ds-dark-theme]` 段:能靠宿主 alias 表达的\n * 一律不写覆盖(alias 自己随主题变),只有「固定中性面 / 半透明底」这类 alias 表达不了的才进该段。\n * - **离散刻度**:圆角 4/8/12/16/20/28、间距 4/8/12/16、控件高 24/28/32、字号 11/12/13/14/16\n * ——业务文件不许出现 5/7/9px、不许自造高度档(要加档位改本文件)。\n *\n * 明暗判据 = `body[data-ds-dark-theme]`(宿主 0.2.0-rc.2 源码核实:启动脚本 toggleAttribute 写入)。\n * 插件**禁用** `prefers-color-scheme`(它跟系统、不跟用户在宿主里的选择)。\n * 因为判据是纯 CSS 选择器 ⇒ 宿主切主题即生效,**不需要 MutationObserver**。\n *\n * 挂载点 = `body`:插件界面(含将来 portal 到 body 的弹层)全在 body 内,零调用点成本。\n */\nexport const UI_TOKENS_CSS = `\nbody{\n /* ── 文字四档 + 反色面 ───────────────────────────────────────── */\n --dtl-fg:var(--dsw-alias-label-primary,#1f2328);\n --dtl-fg-2:var(--dsw-alias-label-secondary,#5c6370);\n --dtl-fg-3:var(--dsw-alias-label-tertiary,#767d87);\n --dtl-fg-4:var(--dsw-alias-label-caption,#9aa1ab);\n --dtl-fg-dim:var(--dsw-alias-label-dimmed,#b9bfc7);\n /* 反色面上的字(角标 / 实心钮):暗色下是 bluish-1000 ⇒ 用 -foreground 而非 -inverted */\n --dtl-fg-inverse:var(--dsw-alias-label-primary-foreground,#fff);\n\n /* ── 面 ──────────────────────────────────────────────────────── */\n --dtl-surface-1:var(--dsw-alias-bg-layer-1,#fff);\n --dtl-surface-2:var(--dsw-alias-bg-layer-2,#fff);\n --dtl-surface-base:var(--dsw-alias-bg-base,#fff);\n /* 「选中亮片」底盘(配 shadow-raised 用) */\n --dtl-surface-raised:var(--dsw-alias-bg-layer-1,#fff);\n /* 固定中性实面(自绘浮标 / 角标这类必须自己变的东西) */\n --dtl-solid:var(--dsw-static-neutral-00,#fff);\n --dtl-on-solid:var(--dsw-alias-label-primary,#1f2328);\n /* 斑马纹 / 次层面(浅色下近白、深色下深一档) */\n --dtl-plate:var(--dsw-static-neutral-50,#fafafa);\n /* 斑马纹:几乎贴着原色的一层(用户 2026-10-18:3% 还是太明显) */\n --dtl-zebra:color-mix(in srgb,var(--dtl-fg) 2%,transparent);\n --dtl-plate-hover:var(--dsw-static-neutral-100,#f5f5f5);\n /* 表头底:浅色比斑马纹再深一档(两者不能撞色) */\n --dtl-head-bg:var(--dsw-static-neutral-100,#f5f5f5);\n\n /* ── 描边四档(宿主真值 l1 4% / l2 10% / l3 12% / l4 16%)────── */\n --dtl-border-faint:var(--dsw-alias-border-l1,#0000000a);\n --dtl-border:var(--dsw-alias-border-l2,#0000001a);\n --dtl-border-strong:var(--dsw-alias-border-l3,#0000001f);\n --dtl-border-heavy:var(--dsw-alias-border-l4,#00000029);\n\n /* ── 语义色 ──────────────────────────────────────────────────── */\n /* 品牌「面」色:明色近黑、暗色近白(实心钮选中态即此),不是蓝 */\n --dtl-accent:var(--dsw-alias-brand-primary,#0f1115);\n /* 蓝色强调 / 选中 / 焦点一律走这条 */\n --dtl-business:var(--dsw-alias-state-business-primary,#3b5bdb);\n --dtl-success:var(--dsw-alias-state-success-primary,#22c55e);\n /* ⚠️ 宿主是 state-warn(不是 state-warning,后者无此定义) */\n --dtl-warning:var(--dsw-alias-state-warn-primary,#f59e0b);\n --dtl-danger:var(--dsw-alias-state-error-primary,#ec1313);\n /* 逾期橙:在「积压黄」与「停滞红」之间再取一档(语义阶梯 灰→黄→橙→红),\n 宿主没有现成的橙 token ⇒ 用 warn + error 两色现算,主题一换自动跟随 */\n --dtl-overdue:color-mix(in srgb,var(--dtl-warning) 55%,var(--dtl-danger));\n --dtl-link:var(--dsw-alias-link,#3b5bdb);\n /* 语义色实面上的字(角标 / 实心提示):红绿黄都是中调 ⇒ 白字两个主题都可读 */\n --dtl-on-signal:#fff;\n /* 语义色浅底:color-mix 现算 ⇒ 跟随宿主 alias,主题一换自动成立 */\n --dtl-business-soft:color-mix(in srgb,var(--dtl-business) 14%,transparent);\n /* 他人任务的 doing 色:比「我的」蓝灰一档(用户 2026-10-17:要和我的蓝区分) */\n --dtl-business-dim:color-mix(in srgb,var(--dtl-business) 55%,var(--dtl-fg-3));\n --dtl-success-soft:color-mix(in srgb,var(--dtl-success) 8%,transparent);\n --dtl-warning-soft:color-mix(in srgb,var(--dtl-warning) 8%,transparent);\n --dtl-danger-soft:color-mix(in srgb,var(--dtl-danger) 8%,transparent);\n\n /* ── 交互底 ──────────────────────────────────────────────────── */\n --dtl-hover:var(--dsw-alias-interactive-bg-hover,rgba(38,49,72,.06));\n --dtl-active:var(--dsw-alias-interactive-bg-active,#2631481a);\n /* 卡 / 行 hover 高亮:淡蓝(灰高亮在卡底上几乎看不出来) */\n --dtl-card-hover:rgba(37,99,235,.07);\n /* 展开行底:带透明度的蓝,透出卡片底色(灰底跟斑马纹分不出来) */\n --dtl-open-bg:rgba(37,99,235,.10);\n --dtl-open-bg-soft:rgba(37,99,235,.05);\n /* chip / 标签小底板:浅色下要看得见 ⇒ 掺 7% 近黑;hover 加倍 */\n --dtl-chip-bg:rgba(15,15,15,.07);\n --dtl-chip-bg-hover:rgba(15,15,15,.14);\n /* 图表「新增」柱:**实底**中性灰。半透明底压在卡上会发糊(用户 2026-10-17:「模模糊糊」) */\n --dtl-chart-created:var(--dsw-static-neutral-300,#d4d4d8);\n /* 图表「没完成」柱:醒目琥珀,与蓝(完成)/ 灰(新增)区分(host 无此件,fallback 兜底) */\n --dtl-chart-remaining:var(--dsw-static-amber-400,#f59e0b);\n\n /* ── 圆角(宿主真值 4/8/12/16/20/28)──────────────────────────── */\n --dtl-radius-xs:var(--dsw-radius-xs,4px);\n --dtl-radius-sm:var(--dsw-radius-sm,8px);\n --dtl-radius-md:var(--dsw-radius-md,12px);\n --dtl-radius-lg:var(--dsw-radius-lg,16px);\n --dtl-radius-xl:var(--dsw-radius-xl,20px);\n --dtl-radius-panel:var(--dsw-radius-panel,28px);\n\n /* ── 间距四拍(只许这四档)────────────────────────────────────── */\n --dtl-space-1:4px;\n --dtl-space-2:8px;\n --dtl-space-3:12px;\n --dtl-space-4:16px;\n\n /* ── 控件高度:离散三档(调用点不许自定义高度)────────────────── */\n --dtl-control-h-sm:24px;\n --dtl-control-h-md:28px;\n --dtl-control-h-lg:32px;\n\n /* ── 字号 / 行高(直绑宿主字号族 11/12/13/14/16)──────────────── */\n --dtl-font-xs:var(--dsw-font-xxxs-11-font-size,11px);\n --dtl-font-sm:var(--dsw-font-xxs-12-font-size,12px);\n --dtl-font-md:var(--dsw-font-xs-13-font-size,13px);\n --dtl-font-lg:var(--dsw-font-s-14-font-size,14px);\n --dtl-font-xl:var(--dsw-font-base-16-font-size,16px);\n --dtl-line-xs:var(--dsw-font-xxxs-11-line-height,14px);\n --dtl-line-sm:var(--dsw-font-xxs-12-line-height,18px);\n --dtl-line-md:var(--dsw-font-xs-13-line-height,20px);\n --dtl-line-lg:var(--dsw-font-s-14-line-height,22px);\n --dtl-line-xl:var(--dsw-font-base-16-line-height,24px);\n --dtl-font-mono:var(--ds-font-family-code,monospace);\n /* 统计卡主数字:宿主字号族最大 16px,看板主数字要更大 ⇒ 单开一档(别处不许直接写 px) */\n --dtl-font-stat:26px;\n\n /* ── 投影 / 动效 / 层级 ──────────────────────────────────────── */\n --dtl-shadow-1:var(--dsw-elevation-soft,0 4px 16px 0 #00000008);\n --dtl-shadow-raised:var(--dsw-elevation-soft,0 4px 16px 0 #00000008);\n --dtl-shadow-2:var(--dsw-shadow-lv3,0 12px 32px 0 #00000014);\n --dtl-dur:var(--ds-transition-duration,.2s);\n --dtl-dur-fast:var(--ds-transition-duration-fast,.12s);\n --dtl-ease:var(--ds-ease-in-out,cubic-bezier(.4,0,.2,1));\n --dtl-z-badge:20;\n}\n\n/* ── 明暗差异的唯一落点 ─────────────────────────────────────────\n 只放 alias 表达不了的固定面 / 半透明底;颜色若能靠 alias 自动跟随,一律不写在这里。 */\nbody[data-ds-dark-theme]{\n --dtl-solid:var(--dsw-static-neutral-900,#0f0f0f);\n --dtl-on-solid:var(--dsw-static-neutral-00,#fff);\n --dtl-plate:var(--dsw-static-neutral-850,#212123);\n --dtl-zebra:color-mix(in srgb,var(--dtl-fg) 2.5%,transparent);\n --dtl-plate-hover:var(--dsw-static-neutral-800,#292929);\n /* 暗色表头反过来:比卡片面亮、比斑马纹浅一档 */\n --dtl-head-bg:var(--dtl-surface-2);\n /* 暗色下蓝要更亮、透明度更高才压得住深底 */\n --dtl-open-bg:rgba(96,165,250,.18);\n --dtl-open-bg-soft:rgba(96,165,250,.08);\n --dtl-card-hover:rgba(96,165,250,.13);\n /* 暗色 chip 底板反过来掺白 */\n --dtl-chip-bg:rgba(255,255,255,.08);\n --dtl-chip-bg-hover:rgba(255,255,255,.16);\n --dtl-chart-created:var(--dsw-static-neutral-600,#525252);\n --dtl-chart-remaining:var(--dsw-static-amber-500,#fbbf24);\n /* 语义色浅底在深色下压到 5%(8% 在深底上偏重) */\n --dtl-business-soft:color-mix(in srgb,var(--dtl-business) 12%,transparent);\n --dtl-business-dim:color-mix(in srgb,var(--dtl-business) 55%,var(--dtl-fg-3));\n --dtl-success-soft:color-mix(in srgb,var(--dtl-success) 5%,transparent);\n --dtl-warning-soft:color-mix(in srgb,var(--dtl-warning) 5%,transparent);\n --dtl-danger-soft:color-mix(in srgb,var(--dtl-danger) 5%,transparent);\n}\n`;\n\n/**\n * 控件皮肤(L2):**一类控件唯一实现**,抄 dispatch 表 controls-css 的规矩——\n * 只消费 var(--dtl-*),一个颜色 / 尺寸 / 圆角 / 字号字面量都不许出现;\n * 高度只取三档,有边框的变体用 1px 真边框 + 内部 padding 补回 ⇒ 有边 / 无边同高。\n */\nexport const UI_CONTROLS_CSS = `\n/* ── 分段控件(滑动块):已改由核心 Segmented 承担,外观 / 尺寸 / 滑块动画全部在 core,\n 本文件不再写任何分段控件样式(core 0.5.0 起删掉 variant 轴,外观只有一套)。── */\n\n/* ── 按钮 / 图标钮 ───────────────────────────────────────────────\n 与 Segmented 同一条高度纪律;variant 只换颜色,结构 / 尺寸 / 交互只此一份。 */\n.dtl-btn{appearance:none;display:inline-flex;align-items:center;justify-content:center;gap:var(--dtl-space-1);\n box-sizing:border-box;border:1px solid transparent;border-radius:var(--dtl-radius-md);\n background:transparent;color:var(--dtl-fg);font-family:inherit;font-weight:500;white-space:nowrap;cursor:pointer;\n transition:background-color var(--dtl-dur-fast) var(--dtl-ease),border-color var(--dtl-dur-fast) var(--dtl-ease),color var(--dtl-dur-fast) var(--dtl-ease),opacity var(--dtl-dur-fast) var(--dtl-ease);}\n.dtl-btn--sm{height:var(--dtl-control-h-sm);padding:0 10px;font-size:var(--dtl-font-sm);line-height:var(--dtl-line-sm);}\n.dtl-btn--md{height:var(--dtl-control-h-md);padding:0 12px;font-size:var(--dtl-font-md);line-height:var(--dtl-line-md);}\n.dtl-btn--lg{height:var(--dtl-control-h-lg);padding:0 14px;font-size:var(--dtl-font-md);line-height:var(--dtl-line-md);}\n.dtl-btn--primary{background:var(--dtl-accent);color:var(--dtl-fg-inverse);}\n.dtl-btn--primary:hover:not(:disabled){opacity:.9;}\n.dtl-btn--outline{background:var(--dtl-surface-1);border-color:var(--dtl-border-strong);color:var(--dtl-fg);}\n.dtl-btn--outline:hover:not(:disabled){background:var(--dtl-hover);}\n.dtl-btn--ghost{color:var(--dtl-fg-2);}\n.dtl-btn--ghost:hover:not(:disabled){background:var(--dtl-hover);color:var(--dtl-fg);}\n.dtl-btn:focus-visible{outline:2px solid var(--dtl-business);outline-offset:2px;}\n.dtl-btn:disabled{cursor:default;opacity:.5;}\n.dtl-iconbtn{appearance:none;display:inline-flex;align-items:center;justify-content:center;box-sizing:border-box;\n border:1px solid transparent;border-radius:var(--dtl-radius-sm);background:transparent;color:var(--dtl-fg-2);\n font-family:inherit;cursor:pointer;flex:none;\n transition:background-color var(--dtl-dur-fast) var(--dtl-ease),border-color var(--dtl-dur-fast) var(--dtl-ease),color var(--dtl-dur-fast) var(--dtl-ease),opacity var(--dtl-dur-fast) var(--dtl-ease);}\n.dtl-iconbtn--sm{width:var(--dtl-control-h-sm);height:var(--dtl-control-h-sm);font-size:var(--dtl-font-sm);}\n.dtl-iconbtn--md{width:var(--dtl-control-h-md);height:var(--dtl-control-h-md);font-size:var(--dtl-font-md);}\n.dtl-iconbtn--lg{width:var(--dtl-control-h-lg);height:var(--dtl-control-h-lg);font-size:var(--dtl-font-md);}\n.dtl-iconbtn--outline{background:var(--dtl-surface-1);border-color:var(--dtl-border);color:var(--dtl-fg-2);}\n.dtl-iconbtn:hover:not(:disabled){background:var(--dtl-hover);color:var(--dtl-fg);}\n.dtl-iconbtn:focus-visible{outline:2px solid var(--dtl-business);outline-offset:1px;}\n.dtl-iconbtn:disabled{cursor:default;opacity:.4;}\n\n/* ── 输入 / 搜索框 / 下拉 ──────────────────────────────────────── */\n.dtl-input{box-sizing:border-box;width:100%;border:1px solid var(--dtl-border);border-radius:var(--dtl-radius-md);\n background:var(--dtl-surface-1);color:var(--dtl-fg);font-family:inherit;outline:none;\n transition:border-color var(--dtl-dur-fast) var(--dtl-ease),box-shadow var(--dtl-dur-fast) var(--dtl-ease);}\n.dtl-input--sm{height:var(--dtl-control-h-sm);padding:0 8px;font-size:var(--dtl-font-sm);line-height:var(--dtl-line-sm);}\n.dtl-input--md{height:var(--dtl-control-h-md);padding:0 10px;font-size:var(--dtl-font-md);line-height:var(--dtl-line-md);}\n.dtl-input--lg{height:var(--dtl-control-h-lg);padding:0 12px;font-size:var(--dtl-font-md);line-height:var(--dtl-line-md);}\n.dtl-input::placeholder{color:var(--dtl-fg-dim);}\n.dtl-input:focus{border-color:var(--dtl-business);box-shadow:0 0 0 1px var(--dtl-business);}\n.dtl-input:disabled{cursor:default;opacity:.5;}\n/* 原生 select: appearance:none + 自绘箭头 ⇒ 与输入框同宗(宿主没有廉价下拉件) */\n.dtl-select{appearance:none;-webkit-appearance:none;box-sizing:border-box;\n border:1px solid var(--dtl-border);border-radius:var(--dtl-radius-md);background:var(--dtl-surface-1);color:var(--dtl-fg);\n font-family:inherit;outline:none;cursor:pointer;\n background-image:url(\"data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23767d87' stroke-width='1.5'><path d='M4 6.5 8 10.5 12 6.5'/></svg>\");\n background-repeat:no-repeat;background-position:right 8px center;background-size:14px;\n transition:border-color var(--dtl-dur-fast) var(--dtl-ease),box-shadow var(--dtl-dur-fast) var(--dtl-ease);}\n.dtl-select--sm{height:var(--dtl-control-h-sm);padding:0 26px 0 8px;font-size:var(--dtl-font-sm);line-height:var(--dtl-line-sm);}\n.dtl-select--md{height:var(--dtl-control-h-md);padding:0 26px 0 10px;font-size:var(--dtl-font-md);line-height:var(--dtl-line-md);}\n.dtl-select--lg{height:var(--dtl-control-h-lg);padding:0 26px 0 12px;font-size:var(--dtl-font-md);line-height:var(--dtl-line-md);}\n.dtl-select:focus{border-color:var(--dtl-business);box-shadow:0 0 0 1px var(--dtl-business);}\n.dtl-select:disabled{cursor:default;opacity:.5;}\n\n/* ── 卡 / chip / 空态 / 列表行(业务壳,皮肤仍只消费 token)────── */\n.dtl-card{background:var(--dtl-surface-1);border:1px solid var(--dtl-border);border-radius:var(--dtl-radius-md);\n transition:background-color var(--dtl-dur-fast) var(--dtl-ease);}\n.dtl-card--clickable{cursor:pointer;text-align:left;font:inherit;color:inherit;width:100%;}\n.dtl-card--clickable:hover{background:var(--dtl-card-hover);}\n.dtl-card--clickable[data-active='true']{border-color:var(--dtl-business);}\n.dtl-card--clickable:focus-visible{outline:2px solid var(--dtl-business);outline-offset:1px;}\n.dtl-chip{display:inline-flex;align-items:center;gap:4px;height:20px;padding:0 8px;border-radius:var(--dtl-radius-sm);\n background:var(--dtl-chip-bg);color:var(--dtl-fg-2);font-size:var(--dtl-font-xs);line-height:var(--dtl-line-xs);white-space:nowrap;}\n.dtl-row{display:flex;align-items:center;gap:var(--dtl-space-2);width:100%;box-sizing:border-box;\n padding:var(--dtl-space-2) var(--dtl-space-3);border:0;border-bottom:1px solid var(--dtl-border-faint);\n background:transparent;font:inherit;color:inherit;text-align:left;cursor:pointer;\n transition:background-color var(--dtl-dur-fast) var(--dtl-ease);}\n.dtl-row:hover{background:var(--dtl-card-hover);}\n.dtl-row:focus-visible{outline:2px solid var(--dtl-business);outline-offset:-2px;}\n.dtl-row[data-open='true']{background:var(--dtl-open-bg);}\n.dtl-row-body{padding:var(--dtl-space-2) var(--dtl-space-3) var(--dtl-space-3);border-bottom:1px solid var(--dtl-border-faint);\n background:var(--dtl-open-bg-soft);font-size:var(--dtl-font-md);}\n.dtl-ellipsis{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}\n\n@media (prefers-reduced-motion: reduce){\n .dtl-seg__item,.dtl-btn,.dtl-iconbtn,.dtl-input,.dtl-select,.dtl-card,.dtl-row{transition:none;}\n}\n`;\n","/**\n * UI 基础层:样式单源 + 共用元件(**一类控件只有一份实现**)。\n *\n * 纪律(用户 2026-10-17「样式与方法一律抽象,不要反复重写」;形态抄本机\n * `dsh-task-dispatch-table` 的 `ui/tokens.ts` + `ui/controls-css.ts` + `ui/*.tsx`):\n * 1. **样式**:颜色 / 圆角 / 字号 / 高度一律 `var(--dtl-*)`(定义只在 tokens.ts),\n * 业务文件不许再写第二份 `var(--dsw-*)`、不许自造 `--dtl-*`、不许自造高度档;\n * 2. **元件**:分段 / 按钮 / 图标钮 / 输入 / 下拉 / 卡 / chip / 空态 / 图表各一份,\n * 页面与浮标共用。官方 primitives 只留「官方做得更好」的(StateDot / MarkdownText / 图标)。\n */\n\nimport { Tooltip } from \"@deepseek-ai/dsh-client-ui-primitives\";\nimport {\n\tButton as CoreButton,\n\tChip as CoreChip,\n\tIconButton as CoreIconButton,\n\tInput as CoreInput,\n\tPicker as CorePicker,\n\tSegmented as CoreSegmented,\n} from \"dsh-plugin-core/ui\";\nimport {\n\ttype CSSProperties,\n\tcreateElement as h,\n\ttype ReactNode,\n\tuseState,\n} from \"react\";\nimport { UI_CONTROLS_CSS, UI_TOKENS_CSS } from \"./tokens\";\n\n/** 条带卡(段头统计条):直接用核心外观,不包第二层皮。 */\nexport { StripCard } from \"dsh-plugin-core/ui\";\n\n/** 基础层样式(tokens + 控件皮肤;幂等注入)。 */\nconst UI_BASE_CSS = `\n/* 统计卡:可点、hover 淡蓝、选中蓝描边 */\n.dtl-stat{display:flex;flex-direction:column;gap:var(--dtl-space-1);\n padding:var(--dtl-space-3) var(--dtl-space-4);text-align:left;}\n.dtl-stat__value{font-size:var(--dtl-font-stat);font-weight:600;line-height:1.15;font-variant-numeric:tabular-nums;}\n.dtl-stat__hint{font-size:var(--dtl-font-xs);line-height:var(--dtl-line-xs);color:var(--dtl-fg-3);}\n\n/* 列表行:分组标题头仍走 .dtl-row-head(可点折叠);任务行走 .dtl-taskrow(两行式,不可点) */\n.dtl-row-head{display:flex;align-items:center;gap:var(--dtl-space-2);\n width:100%;padding:var(--dtl-space-2) var(--dtl-space-3);border:0;background:transparent;\n color:inherit;font:inherit;text-align:left;cursor:pointer;\n transition:background-color var(--dtl-dur-fast) var(--dtl-ease);}\n.dtl-row-head:hover{background:var(--dtl-card-hover);}\n.dtl-row-head:focus-visible{outline:2px solid var(--dtl-business);outline-offset:-2px;}\n\n/* 其他待办 = **一组一张表**(用户 2026-10-18 照参考图 Stripe Payments:Pending / Archived /\n Completed 各一组):组标题是**独立一行**——透明无底、远离上一组、贴近自己的表,\n 文字加粗放大;表体照旧(行下一条线 + 极浅斑马纹)。 */\n/* 组与组**零外距**、连体(用户 2026-10-18:上间距去掉,和上面连在一起) */\n.dtl-group{margin-bottom:0;}\n/* 组标题(段头统计条):改由核心 StripCard 承担(色条 / 底色 / 折叠 caret 全在 core) */\n/* 表格行(.dtl-orow):**零重用**「我的待办」卡片基类——无框、无圆角、无外边距,\n 一行 = 一条底部分隔线 + 极浅斑马纹(用户 2026-10-18:一行一格,不是一块一块的框) */\n.dtl-orow{padding:13px var(--dtl-space-3);border-bottom:1px solid var(--dtl-border-faint);}\n/* 斑马纹落在 2、4、6 行(用户 2026-10-18:原来 1、3、5 看着像从第一行就开始断层) */\n.dtl-orow:nth-of-type(even){background:var(--dtl-zebra);}\n.dtl-orow:hover{background:var(--dtl-card-hover);}\n.dtl-orow__row{display:flex;align-items:center;gap:12px;}\n.dtl-orow__title{display:flex;align-items:baseline;gap:6px;min-width:0;}\n.dtl-orow__name{font-size:var(--dtl-font-md);font-weight:500;line-height:var(--dtl-line-md);min-width:0;}\n/* 第二行:状态标签 + #标签(与标题行间距拉开,用户 2026-10-18;状态位与执行人**互换**后,\n 状态搬到这里、且永远有 ⇒ 这一行不再有「空一排」的情况) */\n.dtl-orow__tags{display:flex;align-items:center;gap:var(--dtl-space-2);margin-top:7px;min-width:0;}\n/* 列:任务(弹性)/ 执行人 / 右侧槽(创建信息 ⇄ 操作钮) */\n.dtl-tcell{min-width:0;}\n.dtl-tcell--title{flex:1 1 auto;}\n/* 执行人列(原状态列,用户 2026-10-18 互换):稍放宽一档(用户 2026-10-19:原来有点挤),\n 20 字的名字能基本摆全;再长由标签自己的省略号兜住,不许溢出压到右边的槽 */\n.dtl-tcell--status{flex:none;width:136px;}\n.dtl-tcell--status .dtl-tag{max-width:100%;}\n/* 悬停:**创建信息整条让位给操作钮**(用户 2026-10-18:不要「掉掉时分秒」那种半吊子,\n 要整条换掉)。两个都**常驻布局**(visibility 切换、不用 display),格子宽度 = 两者较宽的\n 那个 ⇒ hover 时行宽不变、**页面不跳**(跳了执行人的悬停提示就跟着飘) */\n.dtl-orow__slot{display:grid;align-items:center;justify-items:end;flex:none;\n font-size:var(--dtl-font-xs);color:var(--dtl-fg-3);white-space:nowrap;font-variant-numeric:tabular-nums;}\n.dtl-orow__slot>*{grid-area:1/1;}\n.dtl-orow__created{visibility:visible;}\n.dtl-orow__actions{visibility:hidden;display:flex;align-items:center;gap:6px;}\n.dtl-orow:hover .dtl-orow__created{visibility:hidden;}\n.dtl-orow:hover .dtl-orow__actions{visibility:visible;}\n/* 「查看」钮在表格行里也要常驻布局(display:none 会不算宽度 ⇒ hover 一出就又把行撑开) */\n.dtl-orow .dtl-viewbtn{display:inline-flex;visibility:hidden;}\n.dtl-orow:hover .dtl-viewbtn{visibility:visible;}\n/* 行首状态圆点:灰=待认领 / 浅蓝=进行中(比「我的」蓝灰一档)/ 黄=积压 / 橙=逾期 / 红=停滞;\n 6px(用户 2026-10-18:8px 太大) */\n.dtl-dot{display:inline-block;width:6px;height:6px;flex:none;border-radius:50%;}\n.dtl-dot--doing{background:var(--dtl-business-dim);}\n.dtl-dot--backlog{background:var(--dtl-warning);}\n.dtl-dot--overdue{background:var(--dtl-overdue);}\n.dtl-dot--stale{background:var(--dtl-danger);}\n.dtl-dot--open,.dtl-dot--closed{background:var(--dtl-fg-3);}\n\n/* 「查看」钮:与行内动作钮(.dtl-minibtn)同款皮肤、**正方形(26×26,宽=高)**、\n **默认不显、悬停才出来**(用户 2026-10-18:跟认领/继续那几个一起浮现) */\n.dtl-viewbtn{position:relative;display:none;align-items:center;justify-content:center;gap:5px;\n flex:none;width:26px;height:26px;padding:0;border:1px solid var(--dtl-border);\n border-radius:var(--dtl-radius-sm);background:var(--dtl-surface-1);color:var(--dtl-fg-2);\n font:inherit;font-size:var(--dtl-font-sm);line-height:18px;white-space:nowrap;cursor:default;}\n.dtl-viewbtn:hover{border-color:var(--dtl-border-strong);color:var(--dtl-fg);}\n.dtl-taskrow__row:hover .dtl-viewbtn,.dtl-orow:hover .dtl-viewbtn{display:inline-flex;}\n\n/* 任务行 = 一张卡(样式照抄 dispatch-table TaskCard:surface-1 底 + 1px 边框 + 左缘状态条;\n hover 只亮主行;右侧 时间⇄按钮排 互换) */\n.dtl-taskrow{background:var(--dtl-surface-1);border:1px solid var(--dtl-border);\n border-radius:var(--dtl-radius-sm);margin-bottom:10px;}\n.dtl-taskrow__row{display:flex;align-items:center;gap:12px;padding:12px 14px;border-radius:inherit;\n transition:background-color var(--dtl-dur-fast) var(--dtl-ease);}\n.dtl-taskrow__row:hover{background:var(--dtl-card-hover);}\n\n/* 状态条:贴卡片左缘、与正文两行等高的竖向色条(dispatch StatusRail 同款 6×36) */\n.dtl-rail{display:inline-block;width:6px;height:36px;flex:none;border-radius:var(--dtl-radius-xs);}\n.dtl-rail--doing{background:var(--dtl-business);}\n.dtl-rail--backlog{background:var(--dtl-warning);}\n.dtl-rail--overdue{background:var(--dtl-overdue);}\n.dtl-rail--stale{background:var(--dtl-danger);}\n.dtl-rail--open,.dtl-rail--closed{background:var(--dtl-fg-3);}\n\n/* 第一行:标题(上来就是标题)+ [YYYY-MM-DD 创建] 灰徽 + 异常 pill(baseline 对齐,dispatch 同款) */\n.dtl-taskrow__l1{display:flex;align-items:baseline;gap:6px;min-width:0;}\n.dtl-taskrow__title{font-size:var(--dtl-font-lg);font-weight:600;line-height:var(--dtl-line-md);min-width:0;flex:0 1 auto;}\n.dtl-taskrow__stamp{flex:none;font-size:var(--dtl-font-xs);color:var(--dtl-fg-3);white-space:nowrap;\n font-variant-numeric:tabular-nums;}\n/* 第二行小字:工作区 · #标签(行距拉开,用户 2026-10-17:第一二行别贴着) */\n.dtl-taskrow__l2{display:flex;align-items:center;gap:var(--dtl-space-2);margin-top:6px;\n font-size:var(--dtl-font-sm);color:var(--dtl-fg-2);min-width:0;}\n/* 右侧灰字:2026-10-17 开始丨已进行 12 天(用户 2026-10-17:不要蓝,一行灰字) */\n.dtl-taskrow__when{flex:none;font-size:var(--dtl-font-xs);color:var(--dtl-fg-3);white-space:nowrap;\n font-variant-numeric:tabular-nums;}\n.dtl-taskrow__actions{display:none;flex:none;gap:6px;}\n.dtl-taskrow__row:hover .dtl-taskrow__when{display:none;}\n.dtl-taskrow__row:hover .dtl-taskrow__actions{display:inline-flex;}\n\n/* 标签(用户 2026-10-18):状态 / 执行人 / #标签 **共用一枚件**,只换色调。\n 最大宽度 20ch(≈10 个中文或 20 个字符)⇒ 名字上限 20 字;超出**省略号(3 个点)**,\n 悬停把全名补出来(用户 2026-10-19:不跑马灯了)。**没被截 ⇒ 悬停无反应**\n (提示由 Tag 元件按实际宽度决定挂不挂,这里只管裁切)。 */\n.dtl-tag{display:inline-block;flex:none;max-width:20ch;padding:0 6px;border-radius:999px;\n background:var(--dtl-chip-bg);color:var(--dtl-fg-3);font-size:10px;line-height:16px;\n white-space:nowrap;overflow:hidden;text-overflow:ellipsis;vertical-align:middle;}\n/* 状态四色 = **实心色块**(用户 2026-10-18:彩色字看不清 ⇒ 改色块 + 反色字):\n 待认领灰 / 进行中蓝 / 积压黄 / 逾期橙 / 停滞红(与行首圆点同色系)。\n 红黄蓝都是中调 ⇒ 白字两个主题都可读;灰块用「字色底 + 面色字」⇒ 明暗自动反过来 */\n.dtl-tag--open{background:var(--dtl-fg-3);color:var(--dtl-surface-1);font-weight:600;}\n.dtl-tag--doing{background:var(--dtl-business);color:var(--dtl-on-signal);font-weight:600;}\n.dtl-tag--backlog{background:var(--dtl-warning);color:var(--dtl-on-signal);font-weight:600;}\n.dtl-tag--overdue{background:var(--dtl-overdue);color:var(--dtl-on-signal);font-weight:600;}\n.dtl-tag--stale{background:var(--dtl-danger);color:var(--dtl-on-signal);font-weight:600;}\n/* 执行人:浅蓝底(与状态色区分:状态是「事怎么样」,人是「谁在做」) */\n.dtl-tag--person{background:var(--dtl-open-bg-soft);color:var(--dtl-fg-2);}\n/* 用核心 Chip 承担标签时的截断(core Chip 无 max-width/省略号 ⇒ 这里只补布局,不改皮肤) */\n.dshpc-chip.dtl-tagchip{display:inline-block;flex:none;max-width:20ch;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;vertical-align:middle;}\n/* 分区标题里的计数:与日期徽同款中括号小字(用户 2026-10-17);0 条不渲染 */\n.dtl-count{font-size:var(--dtl-font-xs);color:var(--dtl-fg-3);font-variant-numeric:tabular-nums;}\n\n/* 工作区徽标:只铺蓝底(用户 2026-10-17:描边框太抢 ⇒ 去掉;底色已提亮一档见 tokens.ts\n business-soft 8%→14% / 5%→12%),字色回正文。 */\n.dtl-wstag{flex:none;max-width:220px;padding:1px 8px;border-radius:var(--dtl-radius-sm);\n background:var(--dtl-business-soft);color:var(--dtl-fg);\n font-size:var(--dtl-font-xs);line-height:16px;white-space:nowrap;}\n\n/* 行内动作按钮(icon + 字,加大;悬停说明走官方 Tooltip,不在 CSS 里手搓浮层)。\n 样子先行,点击行为归「任务按钮与会话交接」任务 */\n.dtl-minibtn{display:inline-flex;align-items:center;gap:5px;padding:4px 12px;\n border:1px solid var(--dtl-border);border-radius:var(--dtl-radius-sm);\n background:var(--dtl-surface-1);color:var(--dtl-fg-2);font:inherit;font-size:var(--dtl-font-sm);\n line-height:18px;white-space:nowrap;cursor:default;}\n.dtl-minibtn:hover{border-color:var(--dtl-border-strong);color:var(--dtl-fg);}\n\n/* 空态:真空 = 虚线引导卡(用户 2026-10-18:**加高到 180px + 内容居中**;\n 它贴在滚动条最底下,太窄用户根本看不见) */\n.dtl-empty-guide{display:flex;flex-direction:column;align-items:center;justify-content:center;\n gap:var(--dtl-space-2);min-height:270px;padding:var(--dtl-space-4);text-align:center;\n border:1px dashed var(--dtl-border-strong);border-radius:var(--dtl-radius-md);background:transparent;}\n.dtl-empty-filtered{padding:var(--dtl-space-4) 0;color:var(--dtl-fg-3);font-size:var(--dtl-font-md)}\n\n/* 浮标角标:0→n 跳变时一次脉冲,不自动消失 */\n.dtl-badge{position:absolute;top:-2px;right:-2px;min-width:16px;height:16px;padding:0 4px;\n border-radius:8px;background:var(--dtl-danger);color:var(--dtl-on-signal);\n font-size:10px;line-height:16px;text-align:center;font-weight:600;}\n.dtl-badge[data-pulse=\"true\"]{animation:dtl-pulse 900ms var(--dtl-ease) 1}\n@keyframes dtl-pulse{0%{transform:scale(.6);opacity:.4}60%{transform:scale(1.15)}100%{transform:scale(1)}}\n\n/* 统计区整体:左 8 块(2 行 × 4 列)+ 右趋势图,参考图同款分栏。\n ⚠️ 列数写死 4 → 2,绝不给 3:3 列会排出 3+1 的非对称(用户 2026-10-17)。\n 两栏**完全等高**:cards 两行 minmax(0,1fr) 均分 + 卡 height:100% ⇒ 图表卡与左边一样高。 */\n/* 左 8 块略收窄、右图表略放宽(用户 2026-10-17:左再短一丢丢、右长一丢丢) */\n.dtl-stats{display:grid;grid-template-columns:minmax(0,1.7fr) minmax(0,1fr);gap:var(--dtl-space-3);align-items:stretch;}\n.dtl-stats__cards{display:grid;grid-auto-flow:column;grid-template-columns:repeat(4,minmax(0,1fr));grid-template-rows:repeat(2,minmax(0,1fr));\n gap:var(--dtl-space-3);}\n.dtl-stats__cards > .dtl-stat{height:100%;box-sizing:border-box;}\n@media (max-width:960px){.dtl-stats{grid-template-columns:minmax(0,1fr);}}\n@media (max-width:640px){.dtl-stats__cards{grid-template-columns:repeat(2,minmax(0,1fr));grid-template-rows:repeat(4,minmax(0,1fr));}}\n\n/* 「只看我的」小复选框(替掉右上角的分段切换) */\n.dtl-check{display:inline-flex;align-items:center;gap:5px;height:20px;margin-top:-2px;\n font-size:var(--dtl-font-xs);color:var(--dtl-fg-3);cursor:pointer;user-select:none;white-space:nowrap;}\n.dtl-check input{width:12px;height:12px;margin:0;accent-color:var(--dtl-business);cursor:pointer;}\n.dtl-check:hover{color:var(--dtl-fg-2);}\n\n/* 趋势分组柱状图:绘图区高度**随卡拉伸**(flex),柱 / 刻度 / 网格全用百分比 ⇒ 与卡等高 */\n.dtl-gchart-wrap{flex:1 1 auto;min-height:0;display:flex;flex-direction:column;padding-left:30px;padding-bottom:18px;}\n.dtl-gchart{position:relative;flex:1 1 auto;min-height:96px;border-bottom:1px solid var(--dtl-border);}\n.dtl-gchart__grid{position:absolute;left:0;right:0;border-top:1px solid var(--dtl-border-faint);pointer-events:none;}\n.dtl-gchart__ytick{position:absolute;left:-30px;width:26px;text-align:right;font-size:10px;line-height:12px;\n color:var(--dtl-fg-3);transform:translateY(50%);font-variant-numeric:tabular-nums;}\n.dtl-gchart__col{position:absolute;top:0;bottom:0;min-width:0;}\n/* ⚠️ pair 必须 top/bottom 双锚(或 height:100%):绝对定位 + 只给 bottom 时高度是 auto,\n 子元素的 height:% 没有可解析的包含块 ⇒ 整根柱子塌成 0(2026-10-17 真机教训:\n 改百分比柱高后「一个柱子都看不见,只剩数字」)。 */\n.dtl-gchart__pair{position:absolute;top:0;bottom:0;left:50%;transform:translateX(-50%);\n display:flex;align-items:flex-end;gap:1px;}\n/* 三柱:完成(蓝) / 没完成(琥珀) / 新增(灰),每根 5px、无圆角(用户 2026-10-17:太粗、不要圆弧) */\n.dtl-gchart__bar{width:5px;min-height:0;}\n.dtl-gchart__bar--done{background:var(--dtl-business);}\n.dtl-gchart__bar--remaining{background:var(--dtl-chart-remaining);}\n.dtl-gchart__bar--created{background:var(--dtl-chart-created);}\n/* hover:整列三根柱一起提亮(用户 2026-10-17:移上去应该两个都变色,不是只蓝的一根) */\n.dtl-gchart__col:hover .dtl-gchart__bar{filter:brightness(1.18);}\n.dtl-gchart__val{position:absolute;left:50%;transform:translateX(-50%);font-size:10px;line-height:12px;\n color:var(--dtl-fg-2);font-variant-numeric:tabular-nums;white-space:nowrap;}\n.dtl-gchart__label{position:absolute;left:0;right:0;bottom:-16px;text-align:center;\n font-size:10px;line-height:14px;color:var(--dtl-fg-3);white-space:nowrap;}\n/* hover 浮卡(参考图同款:日期 + 两个数;原生 title 太慢、长相不一) */\n.dtl-gchart__tip{position:absolute;top:0;z-index:2;min-width:104px;box-sizing:border-box;\n padding:6px 8px;border:1px solid var(--dtl-border);border-radius:var(--dtl-radius-sm);\n background:var(--dtl-surface-1);box-shadow:var(--dtl-shadow-2);\n font-size:var(--dtl-font-xs);line-height:var(--dtl-line-sm);color:var(--dtl-fg-2);pointer-events:none;}\n.dtl-gchart__tip b{display:block;color:var(--dtl-fg);font-weight:600;}\n.dtl-gchart__tip i{display:inline-block;width:8px;height:8px;border-radius:2px;margin-right:4px;}\n.dtl-gchart-legend{display:flex;align-items:center;gap:var(--dtl-space-3);font-size:var(--dtl-font-xs);color:var(--dtl-fg-2);}\n.dtl-gchart-legend i{display:inline-block;width:8px;height:8px;border-radius:2px;margin-right:4px;}\n\n/* 过程正文:宽度受限、长行折行 */\n.dtl-worklog{max-width:72ch;font-size:var(--dtl-font-md);line-height:1.6}\n`;\n\nconst STYLE_ID = \"dtl-ui-base\";\n\n/** 幂等注入 token 层 + 控件皮肤 + 基础层(面板与浮标谁先挂载都只注入一次)。\n * 已挂载时**就地比对刷新**:插件升级后宿主若复用旧面板 DOM,旧样式表会一直挂着,\n * 导致新版本样式不生效(用户 2026-10-18:0.0.31 装上了圆圈还在)—— 内容变了就原位替换,不必重启。 */\nexport function ensureUiBase(): void {\n\tif (typeof document === \"undefined\") return;\n\tconst css = `${UI_TOKENS_CSS}\\n${UI_CONTROLS_CSS}\\n${UI_BASE_CSS}`;\n\tconst existing = document.getElementById(STYLE_ID);\n\tif (existing !== null) {\n\t\tif (existing.textContent !== css) existing.textContent = css;\n\t\treturn;\n\t}\n\tconst style = document.createElement(\"style\");\n\tstyle.id = STYLE_ID;\n\tstyle.textContent = css;\n\tdocument.head.appendChild(style);\n}\n\n/* ── 分段控件 ─────────────────────────────────────────────────────── */\n\n/** 一段(一个可选值)。 */\nexport interface SegmentedItem<Value extends string = string> {\n\treadonly value: Value;\n\treadonly label: string;\n\t/** 段内角标数字;`undefined` 或 ≤0 不显示。 */\n\treadonly badge?: number;\n}\n\n/** 分段控件(单选):改由核心 `Segmented` 承担(size/滑块动画全在 core,外观只有一套、无需指定变体,\n * 见 core/src/ui/Segmented.ts 头注:2026-10-26 起已删除 variant 轴)。\n * 本地 `badge` 是「灰字计数」语义 ⇒ 映射到 core 的 `count`(core 的 `badge` 是红色危险圆标)。 */\nexport function Segmented<Value extends string>(props: {\n\titems: readonly SegmentedItem<Value>[];\n\tvalue: Value;\n\tonChange: (next: Value) => void;\n\tsize?: \"sm\" | \"md\" | \"lg\";\n\tlabel: string;\n\tid?: string;\n\tstyle?: CSSProperties;\n}): ReactNode {\n\treturn h(CoreSegmented<Value>, {\n\t\titems: props.items.map((item) => ({\n\t\t\tvalue: item.value,\n\t\t\tlabel: item.label,\n\t\t\tcount: item.badge,\n\t\t})),\n\t\tvalue: props.value,\n\t\tonChange: props.onChange,\n\t\t// size 不兜底:不传就吃核心默认档 lg(2026-10-26 用户对图拍板:跟核心 demo 一致,\n\t\t// 之前适配层自作主张降成 md 导致比 demo 矮一档)\n\t\tsize: props.size,\n\t\tlabel: props.label,\n\t\tid: props.id,\n\t\tstyle: props.style,\n\t});\n}\n\n/* ── 按钮 / 图标钮 ────────────────────────────────────────────────── */\n\n/** 按钮:改由核心 `Button` 承担(10 档 variant 里本地用 3 档)。本地默认高度 md(core 默认 lg)。 */\nexport function Button(props: {\n\tchildren?: ReactNode;\n\tonClick?: () => void;\n\tvariant?: \"primary\" | \"outline\" | \"ghost\";\n\tsize?: \"sm\" | \"md\" | \"lg\";\n\ticon?: ReactNode;\n\tdisabled?: boolean;\n\ttitle?: string;\n}): ReactNode {\n\treturn h(\n\t\tCoreButton,\n\t\t{\n\t\t\tvariant: props.variant,\n\t\t\tsize: props.size ?? \"md\",\n\t\t\ticon: props.icon,\n\t\t\tdisabled: props.disabled,\n\t\t\ttitle: props.title,\n\t\t\tonClick: props.onClick,\n\t\t},\n\t\tprops.children,\n\t);\n}\n\n/** 图标钮:改由核心 `IconButton` 承担。 */\nexport function IconButton(props: {\n\ticon: ReactNode;\n\tlabel: string;\n\tonClick?: () => void;\n\tvariant?: \"plain\" | \"outline\";\n\tsize?: \"sm\" | \"md\" | \"lg\";\n\tdisabled?: boolean;\n\ttitle?: string;\n}): ReactNode {\n\treturn h(CoreIconButton, {\n\t\ticon: props.icon,\n\t\tlabel: props.label,\n\t\tonClick: props.onClick,\n\t\tvariant: props.variant ?? \"plain\",\n\t\tsize: props.size ?? \"md\",\n\t\tdisabled: props.disabled,\n\t\ttitle: props.title,\n\t});\n}\n\n/* ── 输入 / 下拉 / 搜索 ───────────────────────────────────────────── */\n\n/** 下拉:改由核心 `Picker`(单选、受控、portal 菜单)承担。\n * 本地 `width`/`minWidth` 核心件暂不支持(`PickerProps` 无 style/width),由外层布局决定宽度。 */\nexport function Select<Value extends string>(props: {\n\tvalue: Value;\n\toptions: readonly { value: Value; label: string }[];\n\tonChange: (next: Value) => void;\n\tariaLabel: string;\n\t/** 定宽(px);核心 Picker 暂不支持,保留签名待 core 补。 */\n\twidth?: number;\n\t/** 最小宽度(px);核心 Picker 暂不支持,保留签名待 core 补。 */\n\tminWidth?: number;\n\tsize?: \"sm\" | \"md\" | \"lg\";\n\t/** 下拉内搜索框(核心 Picker 原生)。 */\n\tsearchable?: boolean;\n}): ReactNode {\n\treturn h(CorePicker, {\n\t\toptions: props.options.map((option) => ({\n\t\t\tvalue: option.value,\n\t\t\tlabel: option.label,\n\t\t})),\n\t\tvalue: props.value,\n\t\tonChange: (next: string | string[]) => {\n\t\t\tprops.onChange(next as Value);\n\t\t},\n\t\tsize: props.size ?? \"md\",\n\t\tsearchable: props.searchable === true,\n\t\tariaLabel: props.ariaLabel,\n\t\tmode: \"single\",\n\t});\n}\n\n/** 搜索框:改由核心 `Input`(type=search)承担;默认铺满容器。 */\nexport function SearchInput(props: {\n\tvalue: string;\n\tplaceholder: string;\n\tonChange: (next: string) => void;\n\tariaLabel: string;\n\tsize?: \"sm\" | \"md\" | \"lg\";\n}): ReactNode {\n\treturn h(CoreInput, {\n\t\ttype: \"search\",\n\t\tvalue: props.value,\n\t\tonChange: props.onChange,\n\t\tplaceholder: props.placeholder,\n\t\tsize: props.size ?? \"md\",\n\t\t\"aria-label\": props.ariaLabel,\n\t});\n}\n\n/* ── 卡 / chip / 空态 ─────────────────────────────────────────────── */\n\n/** 统计卡:主数字 + 灰色口径小字;点一下联动下方列表筛选。\n * `value` 为 0 时显示「—」(用户 2026-10-17 定稿:0 会被读成「没数据 / 出错了」);\n * `hint` 可以是富文本(如把「停滞」两字标红);\n * `interactive: false` = 纯展示卡(统计台:首页没有已结案可筛,不装可点)。 */\nexport function StatCard(props: {\n\tlabel: string;\n\tvalue: string | number;\n\thint?: ReactNode;\n\tactive?: boolean;\n\tinteractive?: boolean;\n\ttitle?: string;\n\tonClick?: () => void;\n}): ReactNode {\n\tensureUiBase();\n\tconst interactive =\n\t\tprops.interactive !== false && props.onClick !== undefined;\n\tconst shown =\n\t\tprops.value === 0 || props.value === \"0\" ? \"—\" : String(props.value);\n\treturn h(\n\t\tinteractive ? \"button\" : \"div\",\n\t\t{\n\t\t\ttype: interactive ? \"button\" : undefined,\n\t\t\tclassName: `dtl-card dtl-stat${interactive ? \" dtl-card--clickable\" : \"\"}`,\n\t\t\t\"data-active\": props.active === true,\n\t\t\ttitle: props.title,\n\t\t\tonClick: interactive ? props.onClick : undefined,\n\t\t},\n\t\th(\n\t\t\t\"span\",\n\t\t\t{ style: { fontSize: \"var(--dtl-font-sm)\", color: \"var(--dtl-fg-2)\" } },\n\t\t\tprops.label,\n\t\t),\n\t\th(\"span\", { className: \"dtl-stat__value\" }, shown),\n\t\tprops.hint === undefined || props.hint === null || props.hint === \"\"\n\t\t\t? null\n\t\t\t: h(\"span\", { className: \"dtl-stat__hint\" }, props.hint),\n\t);\n}\n\n/** chip(分类 / 标签 / 工作区名):改由核心 `Chip` 承担。 */\nexport function Chip(props: { text: string; color?: string }): ReactNode {\n\treturn h(CoreChip, { tone: \"neutral\" }, props.text);\n}\n\n/** 标签上限宽度(字符数):1 个中文按 2 计 ⇒ 10 个中文 = 20 个字符(与 CSS 的 20ch 对齐)。 */\nconst TAG_MAX_WIDTH = 20;\n\n/** 显示宽度:全角(中 / 日 / 韩 / 全角符号)一个顶两个英文字符。 */\nfunction displayWidth(text: string): number {\n\tlet width = 0;\n\tfor (const char of text) width += (char.codePointAt(0) ?? 0) > 0x2e80 ? 2 : 1;\n\treturn width;\n}\n\n/** 本地 7 档语义色 → 核心 `Chip` 5 档。core 缺 doing / backlog / overdue / stale / person 的独立色:\n * overdue 与 stale 都落到 danger、doing 与 person 落到 business(需 core 补 tone 才能精确)。 */\nconst CHIP_TONE: Record<\n\t\"neutral\" | \"open\" | \"backlog\" | \"doing\" | \"overdue\" | \"stale\" | \"person\",\n\t\"neutral\" | \"business\" | \"warning\" | \"danger\"\n> = {\n\tneutral: \"neutral\",\n\topen: \"neutral\",\n\tbacklog: \"warning\",\n\tdoing: \"business\",\n\toverdue: \"danger\",\n\tstale: \"danger\",\n\tperson: \"business\",\n};\n\n/**\n * 标签:状态 / 执行人 / #标签 都走它,只换 tone(改由核心 `Chip` 承担)。\n * 超过 20 个字符宽 ⇒ 省略号(`.dtl-tagchip` 补),**且只在被截时**挂悬停提示补出全文。\n */\nexport function Tag(props: {\n\ttext: string;\n\ttone?:\n\t\t| \"neutral\"\n\t\t| \"open\"\n\t\t| \"backlog\"\n\t\t| \"doing\"\n\t\t| \"overdue\"\n\t\t| \"stale\"\n\t\t| \"person\";\n\t/** 悬停提示(**被截时**才显示;默认 = 文本本身)。 */\n\ttitle?: string;\n\t/** 悬停提示(**始终**显示,状态标记的解释走它;优先于 title)。走官方 Tooltip。 */\n\ttip?: string;\n}): ReactNode {\n\tensureUiBase();\n\tconst { text, tone = \"neutral\", title, tip } = props;\n\tconst long = displayWidth(text) > TAG_MAX_WIDTH;\n\tconst label = tip ?? (long ? (title ?? text) : undefined);\n\tconst chip = h(CoreChip, { tone: CHIP_TONE[tone], className: \"dtl-tagchip\" }, text);\n\tif (label === undefined) return chip;\n\treturn h(Tooltip, {\n\t\tlabel,\n\t\tside: \"bottom\",\n\t\tportal: true,\n\t\tmaxWidth: 240,\n\t\tchildren: chip,\n\t});\n}\n\n/** 空态:`guide` = 真空引导卡(虚线),`filtered` = 筛选空小字。 */\nexport function EmptyState(props: {\n\ttone: \"guide\" | \"filtered\";\n\ttitle: string;\n\thint?: string;\n}): ReactNode {\n\tensureUiBase();\n\tif (props.tone === \"filtered\")\n\t\treturn h(\"div\", { className: \"dtl-empty-filtered\" }, props.title);\n\treturn h(\n\t\t\"div\",\n\t\t{ className: \"dtl-empty-guide\" },\n\t\th(\n\t\t\t\"div\",\n\t\t\t{\n\t\t\t\tstyle: {\n\t\t\t\t\tfontSize: \"var(--dtl-font-lg)\",\n\t\t\t\t\tfontWeight: 600,\n\t\t\t\t\tmarginBottom: \"var(--dtl-space-1)\",\n\t\t\t\t},\n\t\t\t},\n\t\t\tprops.title,\n\t\t),\n\t\tprops.hint === undefined\n\t\t\t? null\n\t\t\t: h(\n\t\t\t\t\t\"div\",\n\t\t\t\t\t{\n\t\t\t\t\t\tstyle: { fontSize: \"var(--dtl-font-md)\", color: \"var(--dtl-fg-2)\" },\n\t\t\t\t\t},\n\t\t\t\t\tprops.hint,\n\t\t\t\t),\n\t);\n}\n\n/** 台账图标(黑白线条,描边走 currentColor ⇒ 随主题 / 选中态反色)。\n * 侧栏条目与右上浮标共用这一份(图标只画一次,别处不许再画第二个)。 */\nexport function LedgerIcon(props: { size?: number }): ReactNode {\n\tconst size = props.size ?? 18;\n\tconst stroke = {\n\t\tfill: \"none\",\n\t\tstroke: \"currentColor\",\n\t\tstrokeWidth: 7,\n\t\tstrokeLinecap: \"round\",\n\t\tstrokeLinejoin: \"round\",\n\t} as const;\n\treturn h(\n\t\t\"svg\",\n\t\t{ width: size, height: size, viewBox: \"0 0 128 128\", \"aria-hidden\": true },\n\t\th(\"path\", {\n\t\t\td: \"M96 34 A10 10 0 0 1 106 44 V102 A10 10 0 0 1 96 112 H32 A10 10 0 0 1 22 102 V44 A10 10 0 0 1 32 34 Z\",\n\t\t\t...stroke,\n\t\t}),\n\t\th(\"path\", { d: \"M50 22 V46 M78 22 V46\", ...stroke }),\n\t\th(\"path\", { d: \"M44 66 H84 M44 86 H70\", ...stroke }),\n\t);\n}\n\n/* ── 趋势分组柱状图 ───────────────────────────────────────────────────── */\n\n/** 一周三根柱(完成 / 没完成 / 新增)。 */\nexport interface GroupedBarWeek {\n\t/** 轴标签(MM-DD)。 */\n\treadonly label: string;\n\treadonly done: number;\n\treadonly remaining: number;\n\treadonly created: number;\n\t/** 悬停文案。 */\n\treadonly title: string;\n}\n\n/** 千位压缩(1.2k / 12k):y 轴刻度与柱顶数值用,避免 4 位数把刻度挤宽。 */\nfunction compactCount(value: number): string {\n\tif (value >= 10_000) return `${Math.round(value / 1000)}k`;\n\tif (value >= 1000) return `${(value / 1000).toFixed(1)}k`;\n\treturn String(value);\n}\n\n/** 分组柱状图(div 柱,无新依赖):完成(蓝)/ 没完成(琥珀)/ 新增(灰)各一细柱。\n * - 高度全用百分比 ⇒ 绘图区随卡片拉伸,图表卡与左边 8 块**完全等高**;\n * - y 轴三档刻度 + 淡网格线;柱顶只标「完成」(3 系列 × 8 周数值会糊成一片);\n * - hover 整列提亮 + 浮卡(日期 + 三个数)——原生 title 太慢;\n * - **没有**均值线与长注释(用户 2026-10-17:均值不要、注释太长不要)。 */\nexport function GroupedBarChart(props: {\n\tweeks: readonly GroupedBarWeek[];\n\tariaLabel: string;\n\tdoneLabel: string;\n\tremainingLabel: string;\n\tcreatedLabel: string;\n}): ReactNode {\n\tensureUiBase();\n\tconst [hover, setHover] = useState<number | null>(null);\n\tconst top = Math.max(\n\t\t1,\n\t\tprops.weeks.reduce(\n\t\t\t(peak, week) => Math.max(peak, week.done, week.remaining, week.created),\n\t\t\t0,\n\t\t),\n\t);\n\tconst ticks = [0, top / 2, top];\n\tconst pct = (value: number): string => `${(value / top) * 100}%`;\n\tconst columnStyle = (index: number): Record<string, string | number> => ({\n\t\tleft: `${(index / props.weeks.length) * 100}%`,\n\t\tright: `${((props.weeks.length - index - 1) / props.weeks.length) * 100}%`,\n\t});\n\t// 浮卡定位:贴边两列向内收,其余居中(否则溢出图表卡)\n\tconst tipStyle = (index: number): Record<string, string | number> => {\n\t\tif (index <= 1) return { left: 0 };\n\t\tif (index >= props.weeks.length - 2) return { right: 0 };\n\t\treturn {\n\t\t\tleft: `${((index + 0.5) / props.weeks.length) * 100}%`,\n\t\t\ttransform: \"translateX(-50%)\",\n\t\t};\n\t};\n\treturn h(\n\t\t\"div\",\n\t\t{ className: \"dtl-gchart-wrap\" },\n\t\th(\n\t\t\t\"div\",\n\t\t\t{\n\t\t\t\tclassName: \"dtl-gchart\",\n\t\t\t\trole: \"img\",\n\t\t\t\t\"aria-label\": props.ariaLabel,\n\t\t\t\tonMouseLeave: () => {\n\t\t\t\t\tsetHover(null);\n\t\t\t\t},\n\t\t\t},\n\t\t\tticks.map((tick) =>\n\t\t\t\th(\"div\", {\n\t\t\t\t\tkey: `grid-${String(tick)}`,\n\t\t\t\t\tclassName: \"dtl-gchart__grid\",\n\t\t\t\t\tstyle: { bottom: pct(tick) },\n\t\t\t\t}),\n\t\t\t),\n\t\t\tticks.map((tick) =>\n\t\t\t\th(\n\t\t\t\t\t\"span\",\n\t\t\t\t\t{\n\t\t\t\t\t\tkey: `tick-${String(tick)}`,\n\t\t\t\t\t\tclassName: \"dtl-gchart__ytick\",\n\t\t\t\t\t\tstyle: { bottom: pct(tick) },\n\t\t\t\t\t},\n\t\t\t\t\tcompactCount(Math.round(tick)),\n\t\t\t\t),\n\t\t\t),\n\t\t\tprops.weeks.map((week, index) =>\n\t\t\t\th(\n\t\t\t\t\t\"div\",\n\t\t\t\t\t{\n\t\t\t\t\t\tkey: week.label,\n\t\t\t\t\t\tclassName: \"dtl-gchart__col\",\n\t\t\t\t\t\tstyle: columnStyle(index),\n\t\t\t\t\t\tonMouseEnter: () => {\n\t\t\t\t\t\t\tsetHover(index);\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\th(\n\t\t\t\t\t\t\"div\",\n\t\t\t\t\t\t{ className: \"dtl-gchart__pair\" },\n\t\t\t\t\t\th(\"span\", {\n\t\t\t\t\t\t\tclassName: \"dtl-gchart__bar dtl-gchart__bar--done\",\n\t\t\t\t\t\t\tstyle: {\n\t\t\t\t\t\t\t\theight: pct(week.done),\n\t\t\t\t\t\t\t\tminHeight: week.done > 0 ? \"2px\" : undefined,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t}),\n\t\t\t\t\t\th(\"span\", {\n\t\t\t\t\t\t\tclassName: \"dtl-gchart__bar dtl-gchart__bar--remaining\",\n\t\t\t\t\t\t\tstyle: {\n\t\t\t\t\t\t\t\theight: pct(week.remaining),\n\t\t\t\t\t\t\t\tminHeight: week.remaining > 0 ? \"2px\" : undefined,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t}),\n\t\t\t\t\t\th(\"span\", {\n\t\t\t\t\t\t\tclassName: \"dtl-gchart__bar dtl-gchart__bar--created\",\n\t\t\t\t\t\t\tstyle: {\n\t\t\t\t\t\t\t\theight: pct(week.created),\n\t\t\t\t\t\t\t\tminHeight: week.created > 0 ? \"2px\" : undefined,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t}),\n\t\t\t\t\t),\n\t\t\t\t\tweek.done === 0\n\t\t\t\t\t\t? null\n\t\t\t\t\t\t: h(\n\t\t\t\t\t\t\t\t\"span\",\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tclassName: \"dtl-gchart__val\",\n\t\t\t\t\t\t\t\t\tstyle: { bottom: `calc(${pct(week.done)} + 3px)` },\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\tString(week.done),\n\t\t\t\t\t\t\t),\n\t\t\t\t\th(\"span\", { className: \"dtl-gchart__label\" }, week.label),\n\t\t\t\t),\n\t\t\t),\n\t\t\thover === null\n\t\t\t\t? null\n\t\t\t\t: h(\n\t\t\t\t\t\t\"div\",\n\t\t\t\t\t\t{ className: \"dtl-gchart__tip\", style: tipStyle(hover) },\n\t\t\t\t\t\th(\"b\", null, props.weeks[hover].title),\n\t\t\t\t\t\th(\n\t\t\t\t\t\t\t\"div\",\n\t\t\t\t\t\t\tnull,\n\t\t\t\t\t\t\th(\"i\", { style: { background: \"var(--dtl-business)\" } }),\n\t\t\t\t\t\t\t`${props.doneLabel} ${props.weeks[hover].done}`,\n\t\t\t\t\t\t),\n\t\t\t\t\t\th(\n\t\t\t\t\t\t\t\"div\",\n\t\t\t\t\t\t\tnull,\n\t\t\t\t\t\t\th(\"i\", { style: { background: \"var(--dtl-chart-remaining)\" } }),\n\t\t\t\t\t\t\t`${props.remainingLabel} ${props.weeks[hover].remaining}`,\n\t\t\t\t\t\t),\n\t\t\t\t\t\th(\n\t\t\t\t\t\t\t\"div\",\n\t\t\t\t\t\t\tnull,\n\t\t\t\t\t\t\th(\"i\", { style: { background: \"var(--dtl-chart-created)\" } }),\n\t\t\t\t\t\t\t`${props.createdLabel} ${props.weeks[hover].created}`,\n\t\t\t\t\t\t),\n\t\t\t\t\t),\n\t\t),\n\t);\n}\n\n/** 图例(完成 / 没完成 / 新增 三个色块)。 */\nexport function ChartLegend(props: {\n\tdoneLabel: string;\n\tremainingLabel: string;\n\tcreatedLabel: string;\n}): ReactNode {\n\tensureUiBase();\n\treturn h(\n\t\t\"div\",\n\t\t{ className: \"dtl-gchart-legend\" },\n\t\th(\n\t\t\t\"span\",\n\t\t\tnull,\n\t\t\th(\"i\", { style: { background: \"var(--dtl-business)\" } }),\n\t\t\tprops.doneLabel,\n\t\t),\n\t\th(\n\t\t\t\"span\",\n\t\t\tnull,\n\t\t\th(\"i\", { style: { background: \"var(--dtl-chart-remaining)\" } }),\n\t\t\tprops.remainingLabel,\n\t\t),\n\t\th(\n\t\t\t\"span\",\n\t\t\tnull,\n\t\t\th(\"i\", { style: { background: \"var(--dtl-chart-created)\" } }),\n\t\t\tprops.createdLabel,\n\t\t),\n\t);\n}\n","/**\n * 任务行(宿主**无表格件** ⇒ 自绘),**两种形态**(用户 2026-10-17 定稿:两区视觉必须不同,\n * 且**互不重用**):\n *\n * A. `mine`(我的待办)= 整行一张卡,样式照抄 dispatch-table 任务配置卡:\n * 左缘 6×36 状态条 + 标题行 + 第二行工作区/标签;右侧灰字时长;悬停出\n * 「继续 / 结束 / 释放」;最右常驻「查看」放大镜钮。\n *\n * B. `others`(全部待办)= 连体长表里的一行(用户 2026-10-18 定稿):**无卡片、无外框**,\n * 行 = 一条淡分隔线格:上下居中的状态圆点 + 任务(标题行 + 标签行;**标签行最前是状态标签**)\n * + **执行人列**(原状态位,有执行人才摆 `@名字` 标签)+ 最右「@创建人 创建于 年-月-日 时:分:秒」\n * (悬停掉时分秒并让位给操作钮)+ 查看。\n * 状态一律**标签型、五色**(用户 2026-10-18:原来是一排素字 / pill,现在与人员**位置互换**):\n * 灰=待认领 / 蓝=进行中 / 黄=积压 / 橙=逾期 / 红=停滞;三个异常标签悬停给**配置出来的**\n * 阈值解释(staleDays / overdueDays / backlogDays 由 host 下发)。圆点颜色同色系。\n *\n * 按钮(含查看)**不各判各的**:权限一律问 `resolveActions()`(rows.ts),本文件只按返回值画。\n *\n * 按钮点击行为(含查看)归「任务按钮与会话交接」任务,本文件只做样子与提示。\n */\n\nimport {\n\tIconCheckOutlineRegular,\n\tIconChevronRightOutlineRegular,\n\tIconDownloadOutlineRegular,\n\tIconSearchOutlineRegular,\n\tTooltip,\n} from \"@deepseek-ai/dsh-client-ui-primitives\";\nimport { createElement as h, type ReactNode } from \"react\";\nimport { formatDateTime } from \"./format\";\nimport type { Translate } from \"./locales\";\nimport { CLOSED_ACTIONS, displayName, type Row, resolveActions } from \"./rows\";\nimport type { BoardPayload } from \"./types\";\nimport { Button, IconButton, Tag } from \"./ui\";\n\ntype Tone = \"doing\" | \"overdue\" | \"stale\" | \"backlog\" | \"open\" | \"closed\";\n\n/** 行标题:在办 = 任务名(缺则任务号);已结案 = 任务包名(缺则「完成了什么」首句)。 */\nfunction titleOf(row: Row): string {\n\tif (row.kind === \"task\") return row.task.title || row.task.id;\n\t// 空串也算「没有」:用 || 而不是 ??,否则空标题会顶掉摘要\n\tconst title = row.record.workpackage || row.record.summary || \"\";\n\treturn title !== \"\" ? title : (row.record.src ?? \"—\");\n}\n\n/** 状态语义(异常优先:停滞 > 逾期 > 积压;三者都是 host 按时间算出来的,不是状态)。\n * 只决定圆点 / 左缘色条这类**单色位**——标签可以多枚,见 MARKS。 */\nfunction toneOf(row: Row): Tone {\n\tif (row.kind !== \"task\") return \"closed\";\n\tif (row.task.stale === true) return \"stale\";\n\tif (row.task.overdue === true) return \"overdue\";\n\tif (row.task.backlog === true) return \"backlog\";\n\tif (row.task.status === \"open\") return \"open\";\n\treturn \"doing\";\n}\n\n/** 三个异常标记**可叠加**(用户 2026-10-19):一条任务能同时逾期 + 停滞,两枚标签都要摆。\n * 积压与逾期 / 停滞不会共存(前者是待认领,后两者是进行中),故最多 2 枚。 */\nconst MARKS = [\"backlog\", \"overdue\", \"stale\"] as const;\n\n/** 状态文案(已结案没有在办状态 ⇒ 不给标签)。 */\nfunction statusLabel(tone: Tone, t: Translate): string | null {\n\tif (tone === \"stale\") return t(\"statusStale\");\n\tif (tone === \"overdue\") return t(\"statusOverdue\");\n\tif (tone === \"backlog\") return t(\"statusBacklog\");\n\tif (tone === \"open\") return t(\"statusOpen\");\n\tif (tone === \"doing\") return t(\"statusActive\");\n\treturn null;\n}\n\nexport function TaskRowView(props: {\n\tt: Translate;\n\trow: Row;\n\t/** 形态:我的待办(卡片)/ 全部待办(表格行)——两区视觉必须不同、互不重用。 */\n\tvariant: \"mine\" | \"others\";\n\t/** 快照:问动作权限(是不是我的 / 能不能认领),并取 host 下发的三个阈值做悬停解释。 */\n\tboard: BoardPayload | null;\n}): ReactNode {\n\tconst { t, row, variant, board } = props;\n\tconst tone = toneOf(row);\n\tconst isTask = row.kind === \"task\";\n\tconst tags = (row.kind === \"task\" ? row.task.tags : row.record.tags) ?? [];\n\n\t// 创建日期(第一行灰徽只给日期)。\n\tconst created =\n\t\trow.kind === \"task\"\n\t\t\t? (row.task.created ?? null)\n\t\t\t: (row.record.created ?? null);\n\tconst createdDay =\n\t\tcreated !== null && created !== undefined && Date.parse(created) >= 0\n\t\t\t? formatDateTime(created).slice(0, 10)\n\t\t\t: null;\n\n\t// 标签悬停解释(用户 2026-10-19):一律「谁 / 何时开始 / 最后更新 / 多少天」,天数由 host 下发,\n\t// 前端不自行推算;缺时间就报「时间未知」,不编。\n\tconst stamp = (value: string | null | undefined): string =>\n\t\tvalue === null || value === undefined\n\t\t\t? t(\"timeUnknown\")\n\t\t\t: formatDateTime(value, { seconds: true, fallback: t(\"timeUnknown\") });\n\tconst dayText = (n: number | null | undefined): string =>\n\t\tn === null || n === undefined ? t(\"daysNone\") : t(\"daysValue\", { n });\n\tconst detailTip = (which: Exclude<Tone, \"closed\">): string | undefined => {\n\t\tif (row.kind !== \"task\") return undefined;\n\t\tconst { task } = row;\n\t\tconst owner = displayName(task.owner_name, task.owner);\n\t\tconst who = owner === \"\" ? t(\"ownerUnclaimed\") : `@${owner}`;\n\t\tconst started = stamp(task.started ?? task.created);\n\t\tconst updated = stamp(task.updated ?? task.started ?? task.created);\n\t\tif (which === \"open\") return t(\"tipOpen\", { created: stamp(task.created) });\n\t\tif (which === \"backlog\")\n\t\t\treturn t(\"tipBacklog\", {\n\t\t\t\tcreated: stamp(task.created),\n\t\t\t\td: dayText(task.waitingDays),\n\t\t\t});\n\t\tif (which === \"doing\") return t(\"tipDoing\", { who, started, updated });\n\t\tif (which === \"overdue\")\n\t\t\treturn t(\"tipOverdue\", {\n\t\t\t\twho,\n\t\t\t\tstarted,\n\t\t\t\tupdated,\n\t\t\t\td: dayText(task.ageDays),\n\t\t\t});\n\t\treturn t(\"tipStale\", { who, started, updated, d: dayText(task.idleDays) });\n\t};\n\t// 动作权限:**唯一**判定(用户 2026-10-18)——两区同一套,不许各判各的;本文件只按返回值画。\n\tconst actions = isTask ? resolveActions(row.task, board) : CLOSED_ACTIONS;\n\n\t// 动作钮:四个 + 查看,各一份(两区共用,不许各画一套)。\n\t// 悬停说明统一走官方 Tooltip(portal 逃逸裁切、hover 即出),不在 CSS 里手搓 ::after 浮层。\n\t// 「查看」:两区都有、统一最右、放大镜图标(用户 2026-10-17)。\n\tconst viewButton = h(Tooltip, {\n\t\tlabel: t(\"viewDetail\"),\n\t\tside: \"bottom\",\n\t\tportal: true,\n\t\tmaxWidth: 240,\n\t\tchildren: h(IconButton, {\n\t\t\tvariant: \"plain\",\n\t\t\tsize: \"sm\",\n\t\t\tlabel: t(\"viewDetail\"),\n\t\t\ticon: h(IconSearchOutlineRegular, { size: 14 }),\n\t\t}),\n\t});\n\tconst tipBtn = (\n\t\ticon: ReactNode,\n\t\tactionKey:\n\t\t\t| \"actionClaim\"\n\t\t\t| \"actionResume\"\n\t\t\t| \"actionFinish\"\n\t\t\t| \"actionRelease\",\n\t\ttipKey: \"tipClaim\" | \"tipResume\" | \"tipFinish\" | \"tipRelease\",\n\t): ReactNode =>\n\t\th(Tooltip, {\n\t\t\tlabel: t(tipKey),\n\t\t\tside: \"bottom\",\n\t\t\tportal: true,\n\t\t\tmaxWidth: 240,\n\t\t\tchildren: h(\n\t\t\t\tButton,\n\t\t\t\t{ variant: \"ghost\", size: \"sm\", icon: icon ?? undefined },\n\t\t\t\tt(actionKey),\n\t\t\t),\n\t\t});\n\tconst claimButton = tipBtn(\n\t\th(IconDownloadOutlineRegular, { size: 14 }),\n\t\t\"actionClaim\",\n\t\t\"tipClaim\",\n\t);\n\tconst resumeButton = tipBtn(\n\t\th(IconChevronRightOutlineRegular, { size: 14 }),\n\t\t\"actionResume\",\n\t\t\"tipResume\",\n\t);\n\tconst finishButton = tipBtn(\n\t\th(IconCheckOutlineRegular, { size: 14 }),\n\t\t\"actionFinish\",\n\t\t\"tipFinish\",\n\t);\n\t// 释放:官方 rc.2 无断链图标(已全量核实)⇒ 纯文字,不用叉\n\tconst releaseButton = tipBtn(null, \"actionRelease\", \"tipRelease\");\n\n\t// 状态标签(五色实心块,用户 2026-10-18 定稿):已结案没有在办状态 ⇒ 不摆;\n\t// 三枚异常标签带 host 配置的阈值解释(没配就不解释,不编)。\n\tconst tagOf = (which: Exclude<Tone, \"closed\">, tip?: string): ReactNode => {\n\t\tconst text = statusLabel(which, t) ?? \"\";\n\t\treturn h(Tag, {\n\t\t\tkey: which,\n\t\t\ttext,\n\t\t\ttone: which,\n\t\t\ttip: tip ?? detailTip(which),\n\t\t});\n\t};\n\tconst markTones = isTask\n\t\t? MARKS.filter((which) => row.task[which] === true)\n\t\t: [];\n\t// 异常标记全部摆出来;一个都没有 ⇒ 退回归属状态(待认领 / 进行中)那一枚\n\tconst statusTags =\n\t\ttone === \"closed\"\n\t\t\t? []\n\t\t\t: (markTones.length > 0\n\t\t\t\t\t? markTones\n\t\t\t\t\t: [tone as Exclude<Tone, \"closed\">]\n\t\t\t\t).map((which) => tagOf(which));\n\t// 「我的待办」卡只摆异常标记(进行中只靠左缘色条,不再重复一枚)\n\tconst alarmTags = markTones.map((which) => tagOf(which));\n\n\t// 第一行(「我的待办」卡):标题 + 创建徽 + 异常标签\n\tconst titleLine = h(\n\t\t\"div\",\n\t\t{ className: \"dtl-taskrow__l1\" },\n\t\th(\n\t\t\t\"span\",\n\t\t\t{ className: \"dtl-taskrow__title dtl-ellipsis\", title: titleOf(row) },\n\t\t\ttitleOf(row),\n\t\t),\n\t\tcreatedDay === null\n\t\t\t? null\n\t\t\t: h(\n\t\t\t\t\t\"span\",\n\t\t\t\t\t{ className: \"dtl-taskrow__stamp\" },\n\t\t\t\t\t`[${t(\"fieldCreatedStamp\", { day: createdDay })}]`,\n\t\t\t\t),\n\t\t...alarmTags,\n\t);\n\n\t// 第一行(表格行):独立类族,不沾卡片基类(用户 2026-10-18)。\n\t// 只有标题 —— 创建信息挪到最右、状态进标签行,标题行不再重复一遍。\n\tconst orowTitleLine = h(\n\t\t\"div\",\n\t\t{ className: \"dtl-orow__title\" },\n\t\th(\n\t\t\t\"span\",\n\t\t\t{ className: \"dtl-orow__name dtl-ellipsis\", title: titleOf(row) },\n\t\t\ttitleOf(row),\n\t\t),\n\t);\n\n\t// ── 形态 B:全部待办 = 真表格行(无卡片、无外框,一行一格)──\n\tif (variant === \"others\") {\n\t\t// 已结案行没有「执行人」列 ⇒ 那格摆**创建人**(owner 会被交接改走,不是“创建于”的人)\n\t\tconst creator = isTask ? row.task.creator : row.record.creator;\n\t\tconst owner = isTask ? row.task.owner : null;\n\t\tconst creatorLabel = displayName(\n\t\t\tisTask ? row.task.creator_name : row.record.creator_name,\n\t\t\tcreator,\n\t\t);\n\t\tconst hasOwner = !(owner === null || owner === undefined || owner === \"\");\n\t\tconst who = creatorLabel === \"\" ? \"—\" : `@${creatorLabel}`;\n\t\tconst createdOk =\n\t\t\tcreated !== null && created !== undefined && Date.parse(created) >= 0;\n\t\t// 执行人的悬停提示(**只在名字被截断时才显示**,见 Tag):全名 + **什么时候开始执行**\n\t\t// (任务上的 started;没有就报「时间未知」,不编)\n\t\tconst startedOk =\n\t\t\tisTask &&\n\t\t\trow.task.started !== null &&\n\t\t\trow.task.started !== undefined &&\n\t\t\tDate.parse(row.task.started) >= 0;\n\t\tconst ownerTip = t(\"startedAt\", {\n\t\t\twho: displayName(isTask ? row.task.owner_name : null, owner),\n\t\t\twhen: startedOk\n\t\t\t\t? formatDateTime(String(row.task.started))\n\t\t\t\t: t(\"timeUnknown\"),\n\t\t});\n\t\t// 标签行:**状态在最前**(原执行人位),#标签跟在后面(用户 2026-10-18 位置互换)\n\t\tconst tagLine = h(\n\t\t\t\"div\",\n\t\t\t{ className: \"dtl-orow__tags\" },\n\t\t\t...statusTags,\n\t\t\ttags.map((tag) => h(Tag, { key: tag, text: `#${tag}` })),\n\t\t);\n\t\treturn h(\n\t\t\t\"div\",\n\t\t\t{ className: \"dtl-orow\" },\n\t\t\th(\n\t\t\t\t\"div\",\n\t\t\t\t{ className: \"dtl-orow__row\" },\n\t\t\t\t// 行标识:上下居中圆点(段头是文件夹/竖线,两处刻意不同)\n\t\t\t\th(\"span\", { className: `dtl-dot dtl-dot--${tone}` }),\n\t\t\t\th(\n\t\t\t\t\t\"div\",\n\t\t\t\t\t{ className: \"dtl-tcell dtl-tcell--title\" },\n\t\t\t\t\torowTitleLine,\n\t\t\t\t\ttagLine,\n\t\t\t\t),\n\t\t\t\t// 执行人列(原状态位):有执行人 ⇒ 一枚 @名字 标签,悬停给「谁 什么时候开始执行」\n\t\t\t\t// (页面不许跳:右侧槽位宽度是常驻的,hover 只换可见性 ⇒ 这个提示不会跟着飘)\n\t\t\t\th(\n\t\t\t\t\t\"span\",\n\t\t\t\t\t{ className: \"dtl-tcell dtl-tcell--status\" },\n\t\t\t\t\t// 名字上限 20 字(Tag 的 20ch);超了 ⇒ 省略号 + 悬停补全名(ownerTip)\n\t\t\t\t\thasOwner\n\t\t\t\t\t\t? h(Tag, {\n\t\t\t\t\t\t\t\t// owner 是 uuid:显示名优先,旧数据没有才退回 uuid\n\t\t\t\t\t\t\t\ttext: `@${displayName(isTask ? row.task.owner_name : null, owner)}`,\n\t\t\t\t\t\t\t\ttone: \"person\",\n\t\t\t\t\t\t\t\ttitle: ownerTip,\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t: null,\n\t\t\t\t),\n\t\t\t\t// 最右**一个槽**:创建信息 ⇄ 操作钮二选一(用户 2026-10-18:悬停就把创建信息整条干掉,\n\t\t\t\t// 按钮顶上那一格;两个都常驻布局 ⇒ 行宽不变、页面不跳)\n\t\t\t\th(\n\t\t\t\t\t\"span\",\n\t\t\t\t\t{ className: \"dtl-orow__slot\" },\n\t\t\t\t\th(\n\t\t\t\t\t\t\"span\",\n\t\t\t\t\t\t{ className: \"dtl-orow__created\" },\n\t\t\t\t\t\tt(\"createdAt\", {\n\t\t\t\t\t\t\twho,\n\t\t\t\t\t\t\twhen: createdOk\n\t\t\t\t\t\t\t\t? formatDateTime(String(created))\n\t\t\t\t\t\t\t\t: t(\"timeUnknown\"),\n\t\t\t\t\t\t}),\n\t\t\t\t\t),\n\t\t\t\t\t// 动作排:**同一排、同一间距**(用户 2026-10-18:查看钮不许单独一档间距);\n\t\t\t\t\t// 谁出来由 resolveActions 说了算 —— 我的 ⇒ 继续/结束/释放,待认领 ⇒ 认领\n\t\t\t\t\th(\n\t\t\t\t\t\t\"span\",\n\t\t\t\t\t\t{ className: \"dtl-orow__actions\" },\n\t\t\t\t\t\tactions.claim ? claimButton : null,\n\t\t\t\t\t\tactions.resume ? resumeButton : null,\n\t\t\t\t\t\tactions.finish ? finishButton : null,\n\t\t\t\t\t\tactions.release ? releaseButton : null,\n\t\t\t\t\t\tactions.view ? viewButton : null,\n\t\t\t\t\t),\n\t\t\t\t),\n\t\t\t),\n\t\t);\n\t}\n\n\t// ── 形态 A:我的待办 = 卡片(dispatch 任务配置卡同款)──\n\tconst parts: string[] = [];\n\tif (isTask) {\n\t\tconst startRaw = row.task.started ?? row.task.created;\n\t\tif (\n\t\t\tstartRaw !== undefined &&\n\t\t\tstartRaw !== null &&\n\t\t\tstartRaw !== \"\" &&\n\t\t\tDate.parse(startRaw) >= 0\n\t\t) {\n\t\t\tparts.push(\n\t\t\t\t`${formatDateTime(startRaw).slice(0, 10)} ${t(\"fieldStarted\")}`,\n\t\t\t);\n\t\t}\n\t\tif (row.task.ageDays !== null && row.task.ageDays !== undefined) {\n\t\t\tparts.push(\n\t\t\t\trow.task.ageDays === 0\n\t\t\t\t\t? t(\"ageToday\")\n\t\t\t\t\t: t(\"ageDaysText\", { n: row.task.ageDays }),\n\t\t\t);\n\t\t}\n\t} else {\n\t\tparts.push(\n\t\t\t`${t(\"fieldFinished\")} ${formatDateTime(row.record.time || row.record.created || \"\", { fallback: t(\"timeUnknown\") })}`,\n\t\t);\n\t}\n\treturn h(\n\t\t\"div\",\n\t\t{ className: \"dtl-taskrow\" },\n\t\th(\n\t\t\t\"div\",\n\t\t\t{ className: \"dtl-taskrow__row\" },\n\t\t\th(\"span\", { className: `dtl-rail dtl-rail--${tone}` }),\n\t\t\th(\n\t\t\t\t\"div\",\n\t\t\t\t{ style: { flex: \"1 1 auto\", minWidth: 0 } },\n\t\t\t\ttitleLine,\n\t\t\t\th(\n\t\t\t\t\t\"div\",\n\t\t\t\t\t{ className: \"dtl-taskrow__l2\" },\n\t\t\t\t\th(\n\t\t\t\t\t\t\"span\",\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tclassName: \"dtl-wstag dtl-ellipsis\",\n\t\t\t\t\t\t\ttitle: row.kind === \"task\" ? row.task.workspace.title : \"\",\n\t\t\t\t\t\t},\n\t\t\t\t\t\trow.kind === \"task\" ? row.task.workspace.title : \"\",\n\t\t\t\t\t),\n\t\t\t\t\ttags.map((tag) => h(Tag, { key: tag, text: `#${tag}` })),\n\t\t\t\t),\n\t\t\t),\n\t\t\th(\n\t\t\t\t\"span\",\n\t\t\t\t{ className: \"dtl-taskrow__when\" },\n\t\t\t\tparts.length === 0 ? t(\"timeUnknown\") : parts.join(\"丨\"),\n\t\t\t),\n\t\t\t// 动作排:继续 / 结束 / 释放 + 查看 —— **同一排、同一间距**\n\t\t\t// (用户 2026-10-18:查看钮原来是独立的一格,离前面的按钮远一档)\n\t\t\t// 谁出来由 resolveActions 说了算(与下面「全部待办」**同一个方法**,不再各判各的)\n\t\t\th(\n\t\t\t\t\"span\",\n\t\t\t\t{ className: \"dtl-taskrow__actions\" },\n\t\t\t\tactions.resume ? resumeButton : null,\n\t\t\t\tactions.finish ? finishButton : null,\n\t\t\t\tactions.release ? releaseButton : null,\n\t\t\t\tactions.view ? viewButton : null,\n\t\t\t),\n\t\t),\n\t);\n}\n","/**\n * 看板首页(`main` 槽整页内容):8 统计卡 + 近 8 周趋势图 + 两区任务列表。\n * 定稿见 docs/design/features/board-home.md §二(2026-10-17 专家组改版);\n * 按钮矩阵归「任务按钮与会话交接」任务(写入路径 A/B 未拍板),本页**不画**任务动作按钮。\n *\n * 刷新纪律(2026-10-17 拍板):挂载首读 + 手动刷新按钮,**不轮询**;空态三分\n * (未就绪不渲染 / 真空引导卡 / 筛选空小字)。\n */\n\nimport {\n\tIconChecklistOutlineRegular,\n\tIconFlatListOutlineRegular,\n\tIconFolderCloseRegular,\n\tIconFolderOpenRegular,\n\tIconRefreshOutlineRegular,\n} from \"@deepseek-ai/dsh-client-ui-primitives\";\nimport {\n\ttype ChangeEvent,\n\tcreateElement as h,\n\ttype ReactNode,\n\tuseEffect,\n\tuseMemo,\n\tuseState,\n\tuseSyncExternalStore,\n} from \"react\";\nimport type { LocaleKey, Translate } from \"./locales\";\nimport { isMine, selectView, type WorkspaceGroup } from \"./rows\";\nimport {\n\tboardSnapshot,\n\tboardSubscribe,\n\trefresh,\n\ttype StatusFilter,\n\tsetQuery,\n} from \"./store\";\nimport { TaskRowView } from \"./task-row\";\nimport type { BoardPayload, PeriodCounts } from \"./types\";\nimport {\n\tButton,\n\tChartLegend,\n\tEmptyState,\n\tensureUiBase,\n\tGroupedBarChart,\n\tSearchInput,\n\tSegmented,\n\tSelect,\n\tStripCard,\n\tStatCard,\n} from \"./ui\";\n\n// 构建期由 tsdown.client.config.ts 的 define 注入(版本读 package.json,编码是编译时刻时间戳)。\ndeclare const __PLUGIN_VERSION__: string;\ndeclare const __BUILD_STAMP__: string;\n\ntype Tab = \"tasks\" | \"stats\";\n\n/** 整页容器:占满中栏、自己滚动。 */\nconst pageStyle: Record<string, string | number> = {\n\theight: \"100%\",\n\twidth: \"100%\",\n\tboxSizing: \"border-box\",\n\toverflow: \"auto\",\n\tpadding: \"24px 22px\",\n\tcolor: \"var(--dtl-fg)\",\n};\nconst headerStyle: Record<string, string | number> = {\n\tdisplay: \"flex\",\n\talignItems: \"center\",\n\tjustifyContent: \"space-between\",\n\tgap: \"var(--dtl-space-3)\",\n\tflexWrap: \"wrap\",\n\tmarginBottom: \"var(--dtl-space-4)\",\n};\nconst titleStyle: Record<string, string | number> = {\n\tfontSize: \"var(--dtl-font-xl)\",\n\tfontWeight: 600,\n};\n/** 标题后的版本 + 构建编码:特别小的字(用户 2026-10-26 要求,一眼确认看到的是不是刚 build 的)。 */\nconst buildTagStyle: Record<string, string | number> = {\n\tmarginLeft: \"var(--dtl-space-2)\",\n\tfontSize: \"10px\",\n\tlineHeight: \"1\",\n\tfontWeight: 400,\n\tcolor: \"var(--dtl-fg-dim)\",\n\tfontVariantNumeric: \"tabular-nums\",\n\twhiteSpace: \"nowrap\",\n};\n/** 统计区:左 8 块(2 行 × 4 列)+ 右趋势图,参考图同款分栏。\n * 列数写死 4 → 2(媒体查询在 ui.ts 的 .dtl-stats / .dtl-stats__cards 里),\n * 绝不给 3 列——3 列会排出 3+1 的非对称(用户 2026-10-17:必须上下对称)。 */\nconst statsRowStyle: Record<string, string | number> = {\n\tmarginBottom: \"var(--dtl-space-4)\",\n};\nconst chartCardStyle: Record<string, string | number> = {\n\tdisplay: \"flex\",\n\tflexDirection: \"column\",\n\tgap: \"var(--dtl-space-2)\",\n\tpadding: \"var(--dtl-space-2) var(--dtl-space-3)\",\n};\nconst hintStyle: Record<string, string | number> = {\n\tfontSize: \"var(--dtl-font-sm)\",\n\tcolor: \"var(--dtl-fg-2)\",\n};\n/** 分区标题行:垂直居中(用户 2026-10-17:图标 / 标题 / 计数不许像下楼梯一样逐个低);\n * 上下留白**翻倍**(用户 2026-10-18:两个大标题太挤)。 */\nconst regionHeadRowStyle: Record<string, string | number> = {\n\tdisplay: \"flex\",\n\talignItems: \"center\",\n\tgap: \"var(--dtl-space-2)\",\n\tmargin: \"calc(var(--dtl-space-4) * 2) 0 calc(var(--dtl-space-2) * 2)\",\n};\nconst regionHeadTitleStyle: Record<string, string | number> = {\n\tfontSize: \"var(--dtl-font-lg)\",\n\tfontWeight: 600,\n};\n/** 工作区下拉最小宽度(用户 2026-10-17:内容自适应,下限 = 旧定宽 175 的 3/4 ≈ 131)。 */\nconst WORKSPACE_SELECT_MIN = 131;\n/** 搜索框宽度(用户 2026-10-17:两区同款,96×2 = 192)。 */\nconst SEARCH_WIDTH = 192;\n\n/** 分组默认折叠阈值(组内太多条时先收起,用户点开)。 */\nconst GROUP_COLLAPSE_OVER = 30;\n\nexport function BoardHome(props: {\n\tt: Translate;\n\tonBack: () => void;\n}): ReactNode {\n\tconst { t, onBack } = props;\n\tensureUiBase();\n\tconst state = useSyncExternalStore(boardSubscribe, boardSnapshot);\n\tconst [tab, setTab] = useState<Tab>(\"tasks\");\n\n\t// 打开面板首读(后端纯按需,无推送无轮询)。\n\tuseEffect(() => {\n\t\tvoid refresh();\n\t}, []);\n\n\tconst board = state.board;\n\tconst view = useMemo(() => selectView(state), [state]);\n\tconst stats = board?.stats;\n\t// 趋势走慢路径(`/board/trend`,读 history):晚到不影响列表;未到 / 失败时由统计卡与图表区各自兜底。\n\tconst trend = state.trend;\n\tconst periods = trend?.trend;\n\tconst trendPending =\n\t\tstate.trendStatus === \"idle\" || state.trendStatus === \"loading\";\n\t/** 快照 + 趋势两段各自的降级工作区(op 不同,合并展示,别装没看见)。 */\n\tconst degraded = [...(board?.degraded ?? []), ...(trend?.degraded ?? [])];\n\t// 工作区下拉候选(用户 2026-10-17):不读系统全量工作区,只从「我的」任务里提取工作区并排重\n\t// ⇒ 没有我任务的工作区不出现;口径与第一区一致(isMine 同源)。\n\tconst workspaceOptions = useMemo(\n\t\t() => [\n\t\t\t{ value: \"\", label: t(\"workspaceAll\") },\n\t\t\t...[\n\t\t\t\t...new Map(\n\t\t\t\t\t(board?.tasks ?? [])\n\t\t\t\t\t\t.filter((task) => isMine(task, board))\n\t\t\t\t\t\t.map((task) => [task.workspace.id, task.workspace.title]),\n\t\t\t\t),\n\t\t\t].map(([id, title]) => ({ value: id, label: title })),\n\t\t],\n\t\t[board, t],\n\t);\n\t/** 统计卡:纯展示(用户 2026-10-17:先全去掉点击,界面定稿后再议滚动 / 筛选联动)。 */\n\tconst card = (\n\t\tlabel: LocaleKey,\n\t\tvalue: number,\n\t\thint: string,\n\t\ttitle?: string,\n\t): ReactNode =>\n\t\th(StatCard, {\n\t\t\tlabel: t(label),\n\t\t\tvalue,\n\t\t\thint,\n\t\t\ttitle,\n\t\t\tinteractive: false,\n\t\t});\n\n\t/** 子集卡占比小字:分母为 0 或自己没有 ⇒ 不显示(不拿 0% 充数)。 */\n\tconst share = (part: number, whole: number, key: LocaleKey): string =>\n\t\tpart > 0 && whole > 0\n\t\t\t? t(key, { n: Math.round((part / whole) * 100) })\n\t\t\t: \"\";\n\n\t/** 统计台卡:不可点(首页没有已结案可筛),hover 给具体日期区间。\n\t * 趋势未到 / 读挂 ⇒ 数字留 '—'(StatCard 对 0 的处理)、小字整条不显示,**不拿 0 充数**。 */\n\tconst periodCard = (\n\t\tlabel: LocaleKey,\n\t\tperiod: PeriodCounts | undefined,\n\t): ReactNode =>\n\t\th(StatCard, {\n\t\t\tlabel: t(label),\n\t\t\tvalue: period?.done ?? 0,\n\t\t\thint:\n\t\t\t\tperiod === undefined\n\t\t\t\t\t? undefined\n\t\t\t\t\t: t(\"statCreatedHint\", { n: period.created }),\n\t\t\tinteractive: false,\n\t\t\ttitle:\n\t\t\t\tperiod === undefined\n\t\t\t\t\t? undefined\n\t\t\t\t\t: t(\"periodRange\", { from: period.from, to: period.to }),\n\t\t});\n\n\tconst [chartScope, setChartScope] = useState<\"all\" | \"mine\">(\"all\");\n\tconst chartWeeks = useMemo(\n\t\t() =>\n\t\t\t(trend?.closed.weekly[chartScope] ?? []).map((bucket) => {\n\t\t\t\t// 容错:host 旧版可能不带 end(客户端/宿主版本错配时),退回用 week,绝不崩面板。\n\t\t\t\tconst end = bucket.end ?? bucket.week ?? \"\";\n\t\t\t\treturn {\n\t\t\t\t\tlabel: end.slice(5) || bucket.week?.slice(5) || \"\",\n\t\t\t\t\tdone: bucket.done,\n\t\t\t\t\tremaining: bucket.remaining,\n\t\t\t\t\tcreated: bucket.created,\n\t\t\t\t\ttitle:\n\t\t\t\t\t\tchartScope === \"mine\"\n\t\t\t\t\t\t\t? `截至 ${end}(${t(\"chartOnlyMine\")})`\n\t\t\t\t\t\t\t: `截至 ${end}`,\n\t\t\t\t};\n\t\t\t}),\n\t\t[trend, chartScope, t],\n\t);\n\tconst chartEmpty = chartWeeks.every(\n\t\t(week) => week.done === 0 && week.created === 0 && week.remaining === 0,\n\t);\n\t/** 被 skill 脚本整行跳过的历史行(列数不对 / 时间不合法):图表数字已少算,要写出来。 */\n\tconst trendWarnings = trend?.warnings ?? [];\n\n\treturn h(\n\t\t\"div\",\n\t\t{ style: pageStyle },\n\t\th(\n\t\t\t\"div\",\n\t\t\t{ style: { display: \"flex\", justifyContent: \"center\" } },\n\t\t\th(\n\t\t\t\t\"div\",\n\t\t\t\t{\n\t\t\t\t\tstyle: {\n\t\t\t\t\t\twidth: \"100%\",\n\t\t\t\t\t\tmaxWidth: \"1280px\",\n\t\t\t\t\t\tminWidth: 0,\n\t\t\t\t\t\tboxSizing: \"border-box\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\th(\n\t\t\t\t\t\"div\",\n\t\t\t\t\t{ style: headerStyle },\n\t\t\t\t\th(\n\t\t\t\t\t\t\"div\",\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tstyle: {\n\t\t\t\t\t\t\t\tdisplay: \"flex\",\n\t\t\t\t\t\t\t\talignItems: \"center\",\n\t\t\t\t\t\t\t\tgap: \"var(--dtl-space-3)\",\n\t\t\t\t\t\t\t\tminWidth: 0,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\th(\n\t\t\t\t\t\t\tButton,\n\t\t\t\t\t\t\t{ variant: \"outline\", size: \"md\", onClick: onBack },\n\t\t\t\t\t\t\t`← ${t(\"backToConversation\")}`,\n\t\t\t\t\t\t),\n\t\t\t\t\t\th(\n\t\t\t\t\t\t\t\"div\",\n\t\t\t\t\t\t\t{ style: titleStyle },\n\t\t\t\t\t\t\tt(\"panelTitle\"),\n\t\t\t\t\t\t\th(\n\t\t\t\t\t\t\t\t\"span\",\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tstyle: buildTagStyle,\n\t\t\t\t\t\t\t\t\ttitle: `v${__PLUGIN_VERSION__} · ${__BUILD_STAMP__}`,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t`v${__PLUGIN_VERSION__} ${__BUILD_STAMP__}`,\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t),\n\t\t\t\t\t),\n\t\t\t\t\th(\n\t\t\t\t\t\t\"div\",\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tstyle: {\n\t\t\t\t\t\t\t\tdisplay: \"flex\",\n\t\t\t\t\t\t\t\talignItems: \"center\",\n\t\t\t\t\t\t\t\tgap: \"var(--dtl-space-2)\",\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\th(Segmented<Tab>, {\n\t\t\t\t\t\t\tid: \"dtl-tab\",\n\t\t\t\t\t\t\tvalue: tab,\n\t\t\t\t\t\t\tlabel: t(\"panelTitle\"),\n\t\t\t\t\t\t\titems: [\n\t\t\t\t\t\t\t\t{ value: \"tasks\", label: t(\"tabTasks\") },\n\t\t\t\t\t\t\t\t{ value: \"stats\", label: t(\"tabStats\") },\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\tonChange: setTab,\n\t\t\t\t\t\t}),\n\t\t\t\t\t\th(\n\t\t\t\t\t\t\tButton,\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tvariant: \"outline\",\n\t\t\t\t\t\t\t\t// lg:与同排 tab 滑轨同高(用户 2026-10-26:一行控件别一大一小)\n\t\t\t\t\t\t\t\tsize: \"lg\",\n\t\t\t\t\t\t\t\ticon: h(IconRefreshOutlineRegular, { size: 16 }),\n\t\t\t\t\t\t\t\tdisabled: state.refreshing,\n\t\t\t\t\t\t\t\ttitle: t(\"refresh\"),\n\t\t\t\t\t\t\t\tonClick: () => {\n\t\t\t\t\t\t\t\t\tvoid refresh();\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tstate.refreshing ? t(\"refreshing\") : t(\"refresh\"),\n\t\t\t\t\t\t),\n\t\t\t\t\t),\n\t\t\t\t),\n\t\t\t\ttab === \"stats\"\n\t\t\t\t\t? // 统计报表尚未开建(另立任务):占位说明,不画假图表。\n\t\t\t\t\t\th(\"div\", { style: hintStyle }, t(\"statsPlaceholder\"))\n\t\t\t\t\t: h(\n\t\t\t\t\t\t\t\"div\",\n\t\t\t\t\t\t\tnull,\n\t\t\t\t\t\t\t// ── 统计区:左 8 块(操作台 4 + 统计台 4)+ 右趋势图 ──\n\t\t\t\t\t\t\tstats === undefined\n\t\t\t\t\t\t\t\t? null\n\t\t\t\t\t\t\t\t: h(\n\t\t\t\t\t\t\t\t\t\t\"div\",\n\t\t\t\t\t\t\t\t\t\t{ className: \"dtl-stats\", style: statsRowStyle },\n\t\t\t\t\t\t\t\t\t\th(\n\t\t\t\t\t\t\t\t\t\t\t\"div\",\n\t\t\t\t\t\t\t\t\t\t\t{ className: \"dtl-stats__cards\" },\n\t\t\t\t\t\t\t\t\t\t\t// 按列成对(用户 2026-10-19 选 A):每列上下是同一对象的两个视角,\n\t\t\t\t\t\t\t\t\t\t\t// 子集关系一眼可见 —— 积压 ⊂ 待认领、逾期 / 停滞 ⊂ 进行中。\n\t\t\t\t\t\t\t\t\t\t\t// DOM 按**列序**写,CSS 的 grid-auto-flow:column 保证 4 列 / 2 列两种排布下都成对。\n\t\t\t\t\t\t\t\t\t\t\t// 小字一律给本卡独有的增量信息,**不重复全集**(用户 2026-10-19):\n\t\t\t\t\t\t\t\t\t\t\t// 三块子集卡一律报**占全集的比例**(用户 2026-10-19 二选一时定占比),0 条时整条不显示。\n\t\t\t\t\t\t\t\t\t\t\tcard(\n\t\t\t\t\t\t\t\t\t\t\t\t\"statMyActive\",\n\t\t\t\t\t\t\t\t\t\t\t\tstats.myActive,\n\t\t\t\t\t\t\t\t\t\t\t\t[\n\t\t\t\t\t\t\t\t\t\t\t\t\tstats.myOverdue > 0\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t? t(\"statMyOverdueHint\", { n: stats.myOverdue })\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t: null,\n\t\t\t\t\t\t\t\t\t\t\t\t\tstats.myStale > 0\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t? t(\"statMyStaleHint\", { n: stats.myStale })\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t: null,\n\t\t\t\t\t\t\t\t\t\t\t\t]\n\t\t\t\t\t\t\t\t\t\t\t\t\t.filter((part) => part !== null)\n\t\t\t\t\t\t\t\t\t\t\t\t\t.join(\" | \"),\n\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t\tcard(\n\t\t\t\t\t\t\t\t\t\t\t\t\"statDoing\",\n\t\t\t\t\t\t\t\t\t\t\t\tstats.doing,\n\t\t\t\t\t\t\t\t\t\t\t\tstats.doing - stats.myActive > 0\n\t\t\t\t\t\t\t\t\t\t\t\t\t? t(\"statDoingHint\", {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tn: stats.doing - stats.myActive,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t\t\t\t\t\t\t: t(\"statDoingAllMine\"),\n\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t\tcard(\n\t\t\t\t\t\t\t\t\t\t\t\t\"statOpen\",\n\t\t\t\t\t\t\t\t\t\t\t\tstats.open,\n\t\t\t\t\t\t\t\t\t\t\t\tstats.oldestOpenDays === null\n\t\t\t\t\t\t\t\t\t\t\t\t\t? \"\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t: t(\"statOpenHint\", { n: stats.oldestOpenDays }),\n\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t\tcard(\n\t\t\t\t\t\t\t\t\t\t\t\t\"statBacklog\",\n\t\t\t\t\t\t\t\t\t\t\t\tstats.backlog,\n\t\t\t\t\t\t\t\t\t\t\t\tshare(stats.backlog, stats.open, \"statBacklogHint\"),\n\t\t\t\t\t\t\t\t\t\t\t\tt(\"statBacklogTitle\", { n: stats.backlogDays }),\n\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t\tcard(\n\t\t\t\t\t\t\t\t\t\t\t\t\"statOverdue\",\n\t\t\t\t\t\t\t\t\t\t\t\tstats.overdue,\n\t\t\t\t\t\t\t\t\t\t\t\tshare(stats.overdue, stats.doing, \"statOverdueHint\"),\n\t\t\t\t\t\t\t\t\t\t\t\tt(\"statOverdueTitle\", { n: stats.overdueDays }),\n\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t\tcard(\n\t\t\t\t\t\t\t\t\t\t\t\t\"statStale\",\n\t\t\t\t\t\t\t\t\t\t\t\tstats.stale,\n\t\t\t\t\t\t\t\t\t\t\t\tshare(stats.stale, stats.doing, \"statStaleHint\"),\n\t\t\t\t\t\t\t\t\t\t\t\tt(\"statStaleTitle\", { n: stats.staleDays }),\n\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t\tperiodCard(\"statWeekDone\", periods?.thisWeek),\n\t\t\t\t\t\t\t\t\t\t\tperiodCard(\"statLastWeekDone\", periods?.lastWeek),\n\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\th(\n\t\t\t\t\t\t\t\t\t\t\t\"div\",\n\t\t\t\t\t\t\t\t\t\t\t{ className: \"dtl-card\", style: chartCardStyle },\n\t\t\t\t\t\t\t\t\t\t\t// 右上角只留一个「只看我的」小复选框:勾上 = 我的,不勾 = 所有(用户 2026-10-17)\n\t\t\t\t\t\t\t\t\t\t\th(\n\t\t\t\t\t\t\t\t\t\t\t\t\"div\",\n\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\tstyle: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tdisplay: \"flex\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\talignItems: \"center\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tjustifyContent: \"flex-end\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\th(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"label\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t{ className: \"dtl-check\" },\n\t\t\t\t\t\t\t\t\t\t\t\t\th(\"input\", {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"checkbox\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tchecked: chartScope === \"mine\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tonChange: (\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tevent: ChangeEvent<HTMLInputElement>,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t) => {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tsetChartScope(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tevent.target.checked ? \"mine\" : \"all\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t\t\t\t\t\t\tt(\"chartOnlyMine\"),\n\t\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t\t// 趋势是慢路径:未到给占位、读挂给兜底文案(带原因),就绪才画图——绝不画空图冒充「没有记录」。\n\t\t\t\t\t\t\t\t\t\t\ttrendPending\n\t\t\t\t\t\t\t\t\t\t\t\t? h(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"div\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tstyle: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t...hintStyle,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tpadding: \"var(--dtl-space-4) 0\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tt(\"chartLoading\"),\n\t\t\t\t\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\t\t\t\t: state.trendStatus === \"error\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t? h(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"div\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tstyle: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t...hintStyle,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tpadding: \"var(--dtl-space-4) 0\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t`${t(\"chartUnavailable\")}${state.trendError === null ? \"\" : `:${state.trendError}`}`,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\t\t\t\t\t: chartEmpty\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t? h(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"div\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tstyle: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t...hintStyle,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tpadding: \"var(--dtl-space-4) 0\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tt(\"chartEmpty\"),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t: h(GroupedBarChart, {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tweeks: chartWeeks,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tariaLabel: t(\"chartTitle\"),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tdoneLabel: t(\"chartLegendDone\"),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tremainingLabel: t(\"chartLegendRemaining\"),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tcreatedLabel: t(\"chartLegendCreated\"),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t\t\t\t\th(ChartLegend, {\n\t\t\t\t\t\t\t\t\t\t\t\tdoneLabel: t(\"chartLegendDone\"),\n\t\t\t\t\t\t\t\t\t\t\t\tremainingLabel: t(\"chartLegendRemaining\"),\n\t\t\t\t\t\t\t\t\t\t\t\tcreatedLabel: t(\"chartLegendCreated\"),\n\t\t\t\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t\t\t\t\t// 被脚本跳过的坏历史行:数字已经少算,必须说出来(悬停看逐条原因)\n\t\t\t\t\t\t\t\t\t\t\ttrendWarnings.length > 0\n\t\t\t\t\t\t\t\t\t\t\t\t? h(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"div\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tstyle: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t...hintStyle,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tcolor: \"var(--dtl-warning)\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ttitle: trendWarnings.join(\"\\n\"),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tt(\"chartWarnings\", {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tn: trendWarnings.length,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\t\t\t\t: null,\n\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t),\n\n\t\t\t\t\t\t\t// ── 列表 ──\n\t\t\t\t\t\t\tstate.status === \"loading\" && board === null\n\t\t\t\t\t\t\t\t? null // 未就绪:不渲染\n\t\t\t\t\t\t\t\t: state.status === \"error\" && board === null\n\t\t\t\t\t\t\t\t\t? h(\n\t\t\t\t\t\t\t\t\t\t\t\"div\",\n\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\tstyle: {\n\t\t\t\t\t\t\t\t\t\t\t\t\tdisplay: \"flex\",\n\t\t\t\t\t\t\t\t\t\t\t\t\talignItems: \"center\",\n\t\t\t\t\t\t\t\t\t\t\t\t\tgap: \"var(--dtl-space-2)\",\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\th(\n\t\t\t\t\t\t\t\t\t\t\t\t\"span\",\n\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\tstyle: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tcolor: \"var(--dtl-danger)\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tfontSize: \"var(--dtl-font-md)\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t`${t(\"loadFailed\")}:${state.error ?? \"\"}`,\n\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t\th(\n\t\t\t\t\t\t\t\t\t\t\t\tButton,\n\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\tvariant: \"outline\",\n\t\t\t\t\t\t\t\t\t\t\t\t\tsize: \"sm\",\n\t\t\t\t\t\t\t\t\t\t\t\t\tonClick: () => {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tvoid refresh();\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\tt(\"retry\"),\n\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\t: board !== null && board.workspaces.length === 0\n\t\t\t\t\t\t\t\t\t\t? h(EmptyState, {\n\t\t\t\t\t\t\t\t\t\t\t\ttone: \"guide\",\n\t\t\t\t\t\t\t\t\t\t\t\ttitle: t(\"emptyNoWorkspace\"),\n\t\t\t\t\t\t\t\t\t\t\t\thint: t(\"emptyNoWorkspaceHint\"),\n\t\t\t\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t\t\t\t: h(\n\t\t\t\t\t\t\t\t\t\t\t\t\"div\",\n\t\t\t\t\t\t\t\t\t\t\t\tnull,\n\t\t\t\t\t\t\t\t\t\t\t\t// 降级横幅:有工作区读挂 ⇒ 红色警告 + 人话原因(单工作区坏不拖垮其余,别装没看见)\n\t\t\t\t\t\t\t\t\t\t\t\tboard !== null && (board.degraded?.length ?? 0) > 0\n\t\t\t\t\t\t\t\t\t\t\t\t\t? h(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"div\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tstyle: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tdisplay: \"flex\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\talignItems: \"flex-start\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tgap: \"var(--dtl-space-2)\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tpadding:\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"var(--dtl-space-2) var(--dtl-space-3)\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tmarginBottom: \"var(--dtl-space-3)\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tborder: \"1px solid var(--dtl-danger)\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tborderRadius: \"var(--dtl-radius-md)\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tbackground: \"var(--dtl-danger-soft)\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tcolor: \"var(--dtl-fg)\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tfontSize: \"var(--dtl-font-sm)\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tlineHeight: \"var(--dtl-line-sm)\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\th(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"span\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tstyle: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tcolor: \"var(--dtl-danger)\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tflex: \"none\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tfontWeight: 600,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tt(\"degradedTitle\"),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\th(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"span\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tnull,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tdegraded\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t.map((item) =>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tt(\"degradedItem\", {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ttitle: item.workspaceTitle,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tmessage: item.message,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t.join(\";\"),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\t\t\t\t\t: null,\n\t\t\t\t\t\t\t\t\t\t\t\t// 第一区:我的待办——定死全量、不过滤(用户 2026-10-17),空了给引导卡;\n\t\t\t\t\t\t\t\t\t\t\t\t// 标题行右侧挂搜索框(只作用第三区),计数用小圆徽\n\t\t\t\t\t\t\t\t\t\t\t\th(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"div\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t{ style: regionHeadRowStyle },\n\t\t\t\t\t\t\t\t\t\t\t\t\th(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"span\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tstyle: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tcolor: \"var(--dtl-fg-3)\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tdisplay: \"inline-flex\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tflex: \"none\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\th(IconChecklistOutlineRegular, { size: 16 }),\n\t\t\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t\t\t\th(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"span\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t{ style: regionHeadTitleStyle },\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tt(\"regionMine\"),\n\t\t\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t\t\t\tview.mine.length > 0\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t? h(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"span\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t{ className: \"dtl-count\" },\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tt(\"mineCount\", { n: view.mine.length }),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t: null,\n\t\t\t\t\t\t\t\t\t\t\t\t\th(\"span\", { style: { flex: \"1 1 auto\" } }),\n\t\t\t\t\t\t\t\t\t\t\t\t\t// 工作区下拉:核心 Picker 带筛选(用户 2026-10-26);控件统一 lg 档\n\t\t\t\t\t\t\t\t\t\t\t\t\th(Select<string>, {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tsearchable: true,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tsize: \"lg\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tvalue: workspaceOptions.some(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t(option) =>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\toption.value === state.query.workspace,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t? state.query.workspace\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t: \"\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\toptions: workspaceOptions,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tariaLabel: t(\"workspaceLabel\"),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tminWidth: WORKSPACE_SELECT_MIN,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tonChange: (next) => {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tsetQuery({ workspace: next });\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t\t\t\t\t\t\t// 搜索框:在下拉右边、与「其他待办」同宽 192(用户 2026-10-17);统一 lg 档\n\t\t\t\t\t\t\t\t\t\t\t\t\th(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"div\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tstyle: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\twidth: `${SEARCH_WIDTH}px`,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tflex: \"none\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\th(SearchInput, {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tsize: \"lg\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tvalue: state.query.keyword,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tplaceholder: t(\"searchPlaceholder\"),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tariaLabel: t(\"searchPlaceholder\"),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tonChange: (next) => {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tsetQuery({ keyword: next });\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t\t\tview.mine.length === 0\n\t\t\t\t\t\t\t\t\t\t\t\t\t? h(EmptyState, {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ttone: \"guide\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ttitle: t(\"mineEmpty\"),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\thint: t(\"mineEmptyHint\"),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t\t\t\t\t\t\t: view.mine.map((row) =>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\th(TaskRowView, {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tkey: row.key,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tt,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\trow,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tvariant: \"mine\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tboard,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t\t\t// 第二区:全部待办 —— **永远渲染**(用户 2026-10-18:选「进行中」没数据也不能整块消失;\n\t\t\t\t\t\t\t\t\t\t\t\t// 且不要过滤掉自己,所以含我的任务,会与第一区重叠——顶部快看 / 底部全量);\n\t\t\t\t\t\t\t\t\t\t\t\t// 标题行:图标 + 名 + 状态滑轨(带全量角标)+ 搜索(最右);表格区无数据给虚线空态\n\t\t\t\t\t\t\t\t\t\t\t\th(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"div\",\n\t\t\t\t\t\t\t\t\t\t\t\t\tnull,\n\t\t\t\t\t\t\t\t\t\t\t\t\th(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"div\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t{ style: regionHeadRowStyle },\n\t\t\t\t\t\t\t\t\t\t\t\t\t\th(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"span\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tstyle: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tcolor: \"var(--dtl-fg-3)\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tdisplay: \"inline-flex\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tflex: \"none\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\th(IconFlatListOutlineRegular, { size: 16 }),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\th(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"span\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tstyle: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t...regionHeadTitleStyle,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tfontSize: \"var(--dtl-font-md)\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tt(\"regionAll\"),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\th(\"span\", { style: { flex: \"1 1 auto\" } }),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t// 状态滑轨:角标 = 第二区**全量**计数(不受滑轨自身影响);0 不标数字\n\t\t\t\t\t\t\t\t\t\t\t\t\t\th(Segmented<StatusFilter>, {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tid: \"dtl-others-status\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tvalue: state.query.status,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tlabel: t(\"statusLabel\"),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\titems: [\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tvalue: \"all\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tlabel: t(\"statusAll\"),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tbadge: orZero(view.allCounts.total),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tvalue: \"active\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tlabel: t(\"statusActive\"),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tbadge: orZero(view.allCounts.doing),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tvalue: \"open\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tlabel: t(\"statusOpen\"),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tbadge: orZero(view.allCounts.open),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tvalue: \"backlog\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tlabel: t(\"statusBacklog\"),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tbadge: orZero(view.allCounts.backlog),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tvalue: \"overdue\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tlabel: t(\"statusOverdue\"),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tbadge: orZero(view.allCounts.overdue),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tvalue: \"stale\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tlabel: t(\"statusStale\"),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tbadge: orZero(view.allCounts.stale),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tonChange: (next) => {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tsetQuery({ status: next });\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\th(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"div\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tstyle: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\twidth: `${SEARCH_WIDTH}px`,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tflex: \"none\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\th(SearchInput, {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tsize: \"lg\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tvalue: state.query.othersKeyword,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tplaceholder: t(\"searchPlaceholder\"),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tariaLabel: t(\"searchPlaceholder\"),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tonChange: (next) => {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tsetQuery({ othersKeyword: next });\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t\t\t\tview.groups.length === 0\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t? // 空态:虚线框 + 两排字 + 按钮(参考 dispatch 空态;按钮先接「回会话」,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// 真正的「起会话建任务」归会话交接任务)\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\th(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"div\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tclassName: \"dtl-empty-guide\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tstyle: { marginTop: \"var(--dtl-space-2)\" },\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\th(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"div\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tstyle: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tfontSize: \"var(--dtl-font-lg)\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tfontWeight: 600,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tmarginBottom: \"var(--dtl-space-1)\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tt(\"allEmptyTitle\"),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\th(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"div\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tstyle: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tfontSize: \"var(--dtl-font-md)\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tcolor: \"var(--dtl-fg-2)\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tmarginBottom: \"var(--dtl-space-3)\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tt(\"allEmptyHint\"),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\th(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tButton,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tvariant: \"primary\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tsize: \"md\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tonClick: onBack,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tt(\"allEmptyAction\"),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t: h(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"div\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t{ style: { marginTop: \"var(--dtl-space-2)\" } },\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tview.groups.map((group) =>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\th(WorkspaceGroupView, {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tkey: group.workspaceId,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tt,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tgroup,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tboard,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t),\n\t\t\t),\n\t\t),\n\t);\n}\n\n/** 角标:>0 才给数字,0 = undefined(不标)。 */\nfunction orZero(n: number): number | undefined {\n\treturn n > 0 ? n : undefined;\n}\n\n/** 一个工作区分组(全部待办表格段):段头(点+名+统计)→ 列头行 → 任务行。\n * 统计口径(用户 2026-10-18):共 N|待办 N|进行中 N 常显(0 也显);\n * 积压 / 逾期 / 停滞**只在 >0 时出现**。 */\nfunction WorkspaceGroupView(props: {\n\tt: Translate;\n\tgroup: WorkspaceGroup;\n\t/** 传下去只为问动作权限(是不是我的)——第二区含我的任务,按钮得跟第一区一致。 */\n\tboard: BoardPayload | null;\n}): ReactNode {\n\tconst { t, group, board } = props;\n\tconst [open, setOpen] = useState(group.rows.length <= GROUP_COLLAPSE_OVER);\n\tconst stats = [\n\t\tt(\"groupTotal\", { n: group.total }),\n\t\tt(\"groupOpen\", { n: group.openCount }),\n\t\tt(\"groupDoing\", { n: group.doingCount }),\n\t\t...(group.backlogCount > 0\n\t\t\t? [t(\"groupBacklog\", { n: group.backlogCount })]\n\t\t\t: []),\n\t\t...(group.overdueCount > 0\n\t\t\t? [t(\"groupOverdue\", { n: group.overdueCount })]\n\t\t\t: []),\n\t\t...(group.staleCount > 0 ? [t(\"groupStale\", { n: group.staleCount })] : []),\n\t].join(\" | \");\n\t// 段头统计条:核心 StripCard(色条 / 浅底 / 折叠 caret 全是核心外观,用户 2026-10-26 拍板)\n\treturn h(\n\t\t\"div\",\n\t\t{ className: \"dtl-group\" },\n\t\th(\n\t\t\tStripCard,\n\t\t\t{\n\t\t\t\taccent: \"business\",\n\t\t\t\texpanded: open,\n\t\t\t\tonToggle: () => {\n\t\t\t\t\tsetOpen(!open);\n\t\t\t\t},\n\t\t\t\t// 统计放核心 action 槽(右侧,垂直居中);caret 由 StripCard 自动补\n\t\t\t\taction: h(\n\t\t\t\t\t\"span\",\n\t\t\t\t\t{\n\t\t\t\t\t\tstyle: {\n\t\t\t\t\t\t\tfontSize: \"var(--dtl-font-xs)\",\n\t\t\t\t\t\t\tcolor: \"var(--dtl-fg-2)\",\n\t\t\t\t\t\t\twhiteSpace: \"nowrap\",\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\tstats,\n\t\t\t\t),\n\t\t\t},\n\t\t\th(\n\t\t\t\t\"div\",\n\t\t\t\t{ style: { display: \"flex\", alignItems: \"center\", gap: 8, minWidth: 0 } },\n\t\t\t\t// 段头标识:展开 = 开文件夹、收起 = 合文件夹;图标缺席就不显示(StripCard 自有色条兜底)\n\t\t\t\tIconFolderOpenRegular === undefined ||\n\t\t\t\t\tIconFolderCloseRegular === undefined\n\t\t\t\t\t? null\n\t\t\t\t\t: h(\n\t\t\t\t\t\t\t\"span\",\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tstyle: {\n\t\t\t\t\t\t\t\t\tdisplay: \"inline-flex\",\n\t\t\t\t\t\t\t\t\tflex: \"none\",\n\t\t\t\t\t\t\t\t\tcolor: \"var(--dtl-fg-3)\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\th(open ? IconFolderOpenRegular : IconFolderCloseRegular, {\n\t\t\t\t\t\t\t\tsize: 14,\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t),\n\t\t\t\th(\n\t\t\t\t\t\"span\",\n\t\t\t\t\t{\n\t\t\t\t\t\tstyle: {\n\t\t\t\t\t\t\tfontSize: \"var(--dtl-font-lg)\",\n\t\t\t\t\t\t\tfontWeight: 700,\n\t\t\t\t\t\t\tlineHeight: \"var(--dtl-line-lg)\",\n\t\t\t\t\t\t\tcolor: \"var(--dtl-fg)\",\n\t\t\t\t\t\t\toverflow: \"hidden\",\n\t\t\t\t\t\t\ttextOverflow: \"ellipsis\",\n\t\t\t\t\t\t\twhiteSpace: \"nowrap\",\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\tgroup.title,\n\t\t\t\t),\n\t\t\t),\n\t\t),\n\t\topen\n\t\t\t? h(\n\t\t\t\t\t\"div\",\n\t\t\t\t\tnull,\n\t\t\t\t\t// 无列头行(用户 2026-10-18:表头就是段头——左工作区名、右统计,不放「任务/创建人」那排)\n\t\t\t\t\tgroup.rows.map((row) =>\n\t\t\t\t\t\th(TaskRowView, {\n\t\t\t\t\t\t\tkey: row.key,\n\t\t\t\t\t\t\tt,\n\t\t\t\t\t\t\trow,\n\t\t\t\t\t\t\tvariant: \"others\",\n\t\t\t\t\t\t\tboard,\n\t\t\t\t\t\t}),\n\t\t\t\t\t),\n\t\t\t\t)\n\t\t\t: null,\n\t);\n}\n","/**\n * 文案唯一真源:命名空间 `dsh-task-ledger`,zh / en 两档。\n *\n * 规矩(docs/design/ui-style.md §五):\n * - 两档**键必须完全对齐**(冒烟有断言),漏一种语言界面就露键名;\n * - 界面上不许出现未登记的硬编码中文;\n * - 占位符一律 `{name}`,由 `interpolateTranslate` 自己替换(不依赖宿主是否支持 params);\n * - 语言切换**跟随宿主**:插件不自备语言开关(注册字典 + 注册项声明 `locale:` ⇒ 宿主渲染器合成 `t` 席位)。\n */\n\n/** 文案键全集(增删键必须同时改 zh / en)。 */\nexport type LocaleKey =\n\t| \"backToConversation\"\n\t| \"panelTitle\"\n\t| \"tabTasks\"\n\t| \"tabStats\"\n\t| \"refresh\"\n\t| \"refreshing\"\n\t| \"loading\"\n\t| \"retry\"\n\t| \"loadFailed\"\n\t| \"degradedTitle\"\n\t| \"degradedItem\"\n\t| \"statsPlaceholder\"\n\t// 统计卡\n\t| \"statMyActive\"\n\t| \"statOpen\"\n\t| \"statOpenHint\"\n\t| \"statDoing\"\n\t| \"statDoingHint\"\n\t| \"statDoingAllMine\"\n\t| \"statBacklog\"\n\t| \"statOverdue\"\n\t| \"statStale\"\n\t| \"statMyOverdueHint\"\n\t| \"statMyStaleHint\"\n\t| \"statBacklogHint\"\n\t| \"statOverdueHint\"\n\t| \"statStaleHint\"\n\t| \"statStaleTitle\"\n\t| \"statOverdueTitle\"\n\t| \"statBacklogTitle\"\n\t| \"statWeekDone\"\n\t| \"statLastWeekDone\"\n\t| \"statCreatedHint\"\n\t| \"daysNone\"\n\t| \"daysValue\"\n\t// 趋势图\n\t| \"chartTitle\"\n\t| \"chartCaption\"\n\t| \"chartBucket\"\n\t| \"chartEmpty\"\n\t| \"chartLoading\"\n\t| \"chartUnavailable\"\n\t| \"chartScopeAll\"\n\t| \"chartScopeMine\"\n\t| \"chartOnlyMine\"\n\t| \"chartWarnings\"\n\t| \"chartLegendDone\"\n\t| \"chartLegendCreated\"\n\t| \"chartLegendRemaining\"\n\t| \"chartAvg\"\n\t| \"periodRange\"\n\t// 筛选行\n\t| \"scopeLabel\"\n\t| \"scopeMine\"\n\t| \"scopeAll\"\n\t| \"statusLabel\"\n\t| \"statusAll\"\n\t| \"statusActive\"\n\t| \"statusOpen\"\n\t| \"statusBacklog\"\n\t| \"statusOverdue\"\n\t| \"statusStale\"\n\t| \"tipOpen\"\n\t| \"tipBacklog\"\n\t| \"tipDoing\"\n\t| \"tipOverdue\"\n\t| \"tipStale\"\n\t| \"workspaceLabel\"\n\t| \"workspaceAll\"\n\t| \"searchPlaceholder\"\n\t// 列表分区\n\t| \"regionMine\"\n\t| \"regionAll\"\n\t| \"showingCount\"\n\t| \"groupTotal\"\n\t| \"groupOpen\"\n\t| \"groupDoing\"\n\t| \"groupBacklog\"\n\t| \"groupOverdue\"\n\t| \"groupStale\"\n\t| \"colTask\"\n\t| \"colCreator\"\n\t| \"colOwner\"\n\t| \"colStatus\"\n\t| \"colTime\"\n\t| \"allEmptyTitle\"\n\t| \"allEmptyHint\"\n\t| \"allEmptyAction\"\n\t| \"expandAria\"\n\t| \"collapseAria\"\n\t| \"ownerUnclaimed\"\n\t| \"fieldCreator\"\n\t| \"fieldOwner\"\n\t| \"fieldCreated\"\n\t| \"fieldStarted\"\n\t| \"fieldFinished\"\n\t| \"timeUnknown\"\n\t| \"ageDaysText\"\n\t| \"ageToday\"\n\t| \"startedAt\"\n\t| \"actionResume\"\n\t| \"actionFinish\"\n\t| \"actionRelease\"\n\t| \"actionClaim\"\n\t| \"tipResume\"\n\t| \"tipFinish\"\n\t| \"tipRelease\"\n\t| \"tipClaim\"\n\t| \"viewDetail\"\n\t| \"createdAt\"\n\t| \"fieldCreatedStamp\"\n\t| \"mineEmpty\"\n\t| \"mineEmptyHint\"\n\t| \"mineCount\"\n\t| \"worklogTitle\"\n\t| \"worklogPath\"\n\t| \"worklogMissing\"\n\t| \"mdCopy\"\n\t| \"mdCopied\"\n\t| \"mdFootnotes\"\n\t// 空态\n\t| \"emptyNoWorkspace\"\n\t| \"emptyNoWorkspaceHint\"\n\t| \"emptyNoTask\"\n\t| \"emptyNoTaskHint\"\n\t| \"emptyFiltered\"\n\t// 浮标入口\n\t| \"badgeTitle\"\n\t| \"openBoard\";\n\n/** 中文(默认档)。 */\nexport const zh: Record<LocaleKey, string> = {\n\tbackToConversation: \"返回会话\",\n\tpanelTitle: \"任务台账\",\n\ttabTasks: \"任务\",\n\ttabStats: \"统计\",\n\trefresh: \"刷新\",\n\trefreshing: \"刷新中\",\n\tloading: \"读取中…\",\n\tretry: \"重试\",\n\tloadFailed: \"读取失败\",\n\tdegradedTitle: \"部分工作区读取失败\",\n\tdegradedItem: \"{title}:{message}\",\n\tstatsPlaceholder:\n\t\t\"统计报表尚未开建(另立任务):这里以后放分类分布、按人完成数、时间线。\",\n\n\tstatMyActive: \"我的待办\",\n\tstatMyOverdueHint: \"逾期 {n}\",\n\tstatMyStaleHint: \"停滞 {n}\",\n\tstatOpen: \"待认领\",\n\tstatOpenHint: \"最长等待 {n} 天\",\n\tstatDoing: \"进行中\",\n\tstatDoingHint: \"他人在办 {n}\",\n\tstatDoingAllMine: \"均为我负责\",\n\tstatBacklog: \"积压\",\n\tstatOverdue: \"逾期\",\n\tstatStale: \"停滞\",\n\tstatBacklogHint: \"占待认领 {n}%\",\n\tstatOverdueHint: \"占进行中 {n}%\",\n\tstatStaleHint: \"占进行中 {n}%\",\n\tstatStaleTitle: \"停滞 = 进行中满 {n} 天没更新\",\n\tstatOverdueTitle: \"逾期 = 认领后满 {n} 天还没结案\",\n\tstatBacklogTitle: \"积压 = 待认领满 {n} 天没人接\",\n\tstatWeekDone: \"本周完成\",\n\tstatLastWeekDone: \"上周完成\",\n\tstatCreatedHint: \"新增 {n}\",\n\tdaysNone: \"—\",\n\tdaysValue: \"{n} 天\",\n\n\tchartTitle: \"近 8 周\",\n\tchartCaption:\n\t\t\"完成(按结案时间)/ 新增(按创建时间),周一起桶;我的 = owner 是我\",\n\tchartBucket: \"{week} 当周:完成 {done} 条,新增 {created} 条\",\n\tchartEmpty: \"近 8 周没有记录\",\n\tchartLoading: \"趋势读取中…(列表已就绪,统计稍后到)\",\n\tchartUnavailable: \"趋势暂时读不到(不影响上面的任务列表)\",\n\tchartScopeAll: \"所有\",\n\tchartScopeMine: \"我的\",\n\tchartOnlyMine: \"只看我的\",\n\tchartWarnings: \"有 {n} 条历史行格式不对被跳过,上面的数字未计入(悬停看明细)\",\n\tchartLegendDone: \"完成\",\n\tchartLegendCreated: \"新增\",\n\tchartLegendRemaining: \"未结\",\n\tchartAvg: \"周均 {n}\",\n\tperiodRange: \"{from} ~ {to}\",\n\n\tscopeLabel: \"范围\",\n\tscopeMine: \"我的\",\n\tscopeAll: \"全部工作区\",\n\tstatusLabel: \"状态\",\n\tstatusAll: \"全部\",\n\tstatusActive: \"进行中\",\n\tstatusOpen: \"待认领\",\n\tstatusBacklog: \"积压\",\n\tstatusOverdue: \"逾期\",\n\tstatusStale: \"停滞\",\n\ttipOpen: \"任务创建于 {created}\\n尚未有人认领\",\n\ttipBacklog: \"任务创建于 {created}\\n无人认领已满 {d}\",\n\ttipDoing: \"{who}\\n开始执行:{started}\\n最后更新:{updated}\",\n\ttipOverdue: \"{who}\\n开始执行:{started}\\n最后更新:{updated}\\n已逾期 {d}\",\n\ttipStale: \"{who}\\n开始执行:{started}\\n最后更新:{updated}\\n已停滞 {d}\",\n\tworkspaceLabel: \"工作区\",\n\tworkspaceAll: \"全部工作区\",\n\tsearchPlaceholder: \"搜索\",\n\n\tregionMine: \"我的待办\",\n\tregionAll: \"全部待办\",\n\tshowingCount: \"显示 {n} 条\",\n\tgroupTotal: \"共 {n} 条\",\n\tgroupOpen: \"待办 {n} 条\",\n\tgroupDoing: \"进行中 {n} 条\",\n\tgroupBacklog: \"积压 {n} 条\",\n\tgroupOverdue: \"逾期 {n} 条\",\n\tgroupStale: \"停滞 {n} 条\",\n\tcolTask: \"任务\",\n\tcolCreator: \"创建人\",\n\tcolOwner: \"执行人\",\n\tcolStatus: \"状态\",\n\tcolTime: \"时长\",\n\tallEmptyTitle: \"没有可显示的事项\",\n\tallEmptyHint: \"切换上面的状态过滤试试,或新建一个任务。\",\n\tallEmptyAction: \"新建任务\",\n\texpandAria: \"展开过程文档\",\n\tcollapseAria: \"收起\",\n\n\townerUnclaimed: \"待认领\",\n\tfieldCreator: \"创建\",\n\tfieldOwner: \"执行\",\n\tfieldCreated: \"创建\",\n\tfieldStarted: \"开始\",\n\tfieldFinished: \"结案\",\n\ttimeUnknown: \"时间未知\",\n\tageDaysText: \"已进行 {n} 天\",\n\tageToday: \"今天\",\n\tactionResume: \"继续\",\n\tactionFinish: \"结束\",\n\tactionRelease: \"释放\",\n\ttipResume: \"继续推进这个任务\",\n\ttipFinish: \"结案并写入历史\",\n\ttipRelease: \"释放认领,让别人接手\",\n\tactionClaim: \"认领\",\n\ttipClaim: \"认领这个任务,变成我在做\",\n\tcreatedAt: \"{who} 创建于 {when}\",\n\tstartedAt: \"{who} 开始于 {when}\",\n\tviewDetail: \"查看详情\",\n\tfieldCreatedStamp: \"{day} 创建\",\n\tmineEmpty: \"您现在没有正在进行的工作\",\n\tmineEmptyHint:\n\t\t\"在某个工作区 new 一个任务,或到下面认领一条待认领任务,这里就会出现。\",\n\tmineCount: \"{n} 条\",\n\tworklogTitle: \"过程文档\",\n\tworklogPath: \"路径\",\n\tworklogMissing: \"(缺失)\",\n\tmdCopy: \"复制\",\n\tmdCopied: \"已复制\",\n\tmdFootnotes: \"脚注\",\n\n\temptyNoWorkspace: \"还没有台账工作区\",\n\temptyNoWorkspaceHint:\n\t\t\"在某个项目里跑一条 task-ledger skill 的写命令(第一条会自动建档 ledger/pool.json),这里就会出现它。\",\n\temptyNoTask: \"一条任务都没有\",\n\temptyNoTaskHint:\n\t\t\"用 task-ledger skill 的 new 开一个任务,或让别人开在这里等你认领。\",\n\temptyFiltered: \"没有符合当前筛选的任务\",\n\n\tbadgeTitle: \"我名下待办\",\n\topenBoard: \"打开任务台账\",\n};\n\n/** English(与 zh 键完全对齐)。 */\nexport const en: Record<LocaleKey, string> = {\n\tbackToConversation: \"Back to chat\",\n\tpanelTitle: \"Task ledger\",\n\ttabTasks: \"Tasks\",\n\ttabStats: \"Stats\",\n\trefresh: \"Refresh\",\n\trefreshing: \"Refreshing\",\n\tloading: \"Loading…\",\n\tretry: \"Retry\",\n\tloadFailed: \"Load failed\",\n\tdegradedTitle: \"Some workspaces failed to load\",\n\tdegradedItem: \"{title}: {message}\",\n\tstatsPlaceholder:\n\t\t\"Stats reports are not built yet (separate task): category breakdown, completions by person, timeline.\",\n\n\tstatMyActive: \"My todos\",\n\tstatMyOverdueHint: \"overdue {n}\",\n\tstatMyStaleHint: \"stale {n}\",\n\tstatOpen: \"Unclaimed\",\n\tstatOpenHint: \"longest waiting {n} days\",\n\tstatDoing: \"In progress\",\n\tstatDoingHint: \"others: {n}\",\n\tstatDoingAllMine: \"all mine\",\n\tstatBacklog: \"Backlog\",\n\tstatOverdue: \"Overdue\",\n\tstatStale: \"Stale\",\n\tstatBacklogHint: \"{n}% of unclaimed\",\n\tstatOverdueHint: \"{n}% of active\",\n\tstatStaleHint: \"{n}% of active\",\n\tstatStaleTitle: \"stale = active with no update for {n}+ days\",\n\tstatOverdueTitle: \"overdue = claimed {n}+ days ago and still open\",\n\tstatBacklogTitle: \"backlog = unclaimed for {n}+ days\",\n\tstatWeekDone: \"Done this week\",\n\tstatLastWeekDone: \"Done last week\",\n\tstatCreatedHint: \"{n} created\",\n\tdaysNone: \"—\",\n\tdaysValue: \"{n}d\",\n\n\tchartTitle: \"Last 8 weeks\",\n\tchartCaption:\n\t\t\"done (by close time) / created (by create time), weeks start Monday; mine = owner is me\",\n\tchartBucket: \"week of {week}: {done} done, {created} created\",\n\tchartEmpty: \"Nothing in the last 8 weeks\",\n\tchartLoading: \"Loading trend… (list is ready, stats will follow)\",\n\tchartUnavailable:\n\t\t\"Trend is unavailable right now (the task lists above are unaffected)\",\n\tchartScopeAll: \"All\",\n\tchartScopeMine: \"Mine\",\n\tchartOnlyMine: \"Mine only\",\n\tchartWarnings:\n\t\t\"{n} history rows were skipped as malformed and are not counted above (hover for detail)\",\n\tchartLegendDone: \"Done\",\n\tchartLegendCreated: \"Created\",\n\tchartLegendRemaining: \"Outstanding\",\n\tchartAvg: \"avg {n}/wk\",\n\tperiodRange: \"{from} ~ {to}\",\n\n\tscopeLabel: \"Scope\",\n\tscopeMine: \"Mine\",\n\tscopeAll: \"All workspaces\",\n\tstatusLabel: \"Status\",\n\tstatusAll: \"All\",\n\tstatusActive: \"Active\",\n\tstatusOpen: \"Unclaimed\",\n\tstatusBacklog: \"Backlog\",\n\tstatusOverdue: \"Overdue\",\n\tstatusStale: \"Stale\",\n\ttipOpen: \"Created on {created}\\nNot claimed yet\",\n\ttipBacklog: \"Created on {created}\\nUnclaimed for {d}\",\n\ttipDoing: \"{who}\\nStarted: {started}\\nLast updated: {updated}\",\n\ttipOverdue:\n\t\t\"{who}\\nStarted: {started}\\nLast updated: {updated}\\nOverdue by {d}\",\n\ttipStale:\n\t\t\"{who}\\nStarted: {started}\\nLast updated: {updated}\\nStalled for {d}\",\n\tworkspaceLabel: \"Workspace\",\n\tworkspaceAll: \"All workspaces\",\n\tsearchPlaceholder: \"Search\",\n\n\tregionMine: \"My todos\",\n\tregionAll: \"All tasks\",\n\tshowingCount: \"{n} shown\",\n\tgroupTotal: \"{n} total\",\n\tgroupOpen: \"{n} open\",\n\tgroupDoing: \"{n} active\",\n\tgroupBacklog: \"{n} backlog\",\n\tgroupOverdue: \"{n} overdue\",\n\tgroupStale: \"{n} stale\",\n\tcolTask: \"Task\",\n\tcolCreator: \"Created by\",\n\tcolOwner: \"Owner\",\n\tcolStatus: \"Status\",\n\tcolTime: \"Duration\",\n\tallEmptyTitle: \"Nothing to show\",\n\tallEmptyHint: \"Try another status filter above, or create a task.\",\n\tallEmptyAction: \"New task\",\n\texpandAria: \"Expand worklog\",\n\tcollapseAria: \"Collapse\",\n\n\townerUnclaimed: \"unclaimed\",\n\tfieldCreator: \"created by\",\n\tfieldOwner: \"owner\",\n\tfieldCreated: \"created\",\n\tfieldStarted: \"started\",\n\tfieldFinished: \"closed\",\n\ttimeUnknown: \"unknown time\",\n\tageDaysText: \"active {n}d\",\n\tageToday: \"today\",\n\tactionResume: \"Resume\",\n\tactionFinish: \"Close\",\n\tactionRelease: \"Release\",\n\ttipResume: \"keep working on this task\",\n\ttipFinish: \"close and archive it\",\n\ttipRelease: \"release the claim for others\",\n\tactionClaim: \"Claim\",\n\ttipClaim: \"claim this task for yourself\",\n\tcreatedAt: \"created by {who} on {when}\",\n\tstartedAt: \"{who} started on {when}\",\n\tviewDetail: \"View details\",\n\tfieldCreatedStamp: \"created {day}\",\n\tmineEmpty: \"Nothing in progress right now\",\n\tmineEmptyHint:\n\t\t\"Create a task in a workspace or claim one below, and it shows up here.\",\n\tmineCount: \"{n} items\",\n\tworklogTitle: \"Worklog\",\n\tworklogPath: \"path\",\n\tworklogMissing: \"(missing)\",\n\tmdCopy: \"Copy\",\n\tmdCopied: \"Copied\",\n\tmdFootnotes: \"Footnotes\",\n\n\temptyNoWorkspace: \"No ledger workspace yet\",\n\temptyNoWorkspaceHint:\n\t\t\"Run any task-ledger skill write command in a project (the first one creates ledger/pool.json) and it shows up here.\",\n\temptyNoTask: \"No tasks yet\",\n\temptyNoTaskHint:\n\t\t\"Create one with the task-ledger skill new, or leave one here for others to claim.\",\n\temptyFiltered: \"No tasks match the current filters\",\n\n\tbadgeTitle: \"my todos\",\n\topenBoard: \"Open task ledger\",\n};\n\n/** 翻译函数类型(宿主渲染器按 `locale:` 声明合成的 `t` 席位同形)。 */\nexport type Translate = (\n\tkey: LocaleKey,\n\tparams?: Record<string, string | number>,\n) => string;\n\n/** 把宿主给的无参 t 包成带占位符替换的 t(模板一律 `{name}`,不依赖宿主是否支持 params)。 */\nexport function interpolateTranslate(base: Translate): Translate {\n\treturn (key, params) => {\n\t\tconst raw = base(key);\n\t\tif (params === undefined) return raw;\n\t\treturn raw.replace(/\\{(\\w+)\\}/g, (match, name: string) =>\n\t\t\tname in params ? String(params[name]) : match,\n\t\t);\n\t};\n}\n\n/** 键名兜底:宿主没给 t 席位时用(键名绝不上界面)。 */\nexport function fallbackTranslate(\n\tkey: LocaleKey,\n\tparams?: Record<string, string | number>,\n): string {\n\treturn interpolateTranslate((name) => zh[name] ?? name)(key, params);\n}\n","/**\n * 浏览器半入口(client bundle,产物 dist/client.js):装配层,不写业务逻辑。\n *\n * 三处注册各自挂进「服务就位才触发」的 slots 注入(参考插件真机教训:顶层 inject 声明\n * 组合满足不了的依赖会让 entry 一直 pending、卡死整个 dsh 启动):\n * · locale 字典(zh / en)——界面语言跟随宿主,插件不自备开关;\n * · `main` keyed 槽整页(看板首页)。\n *\n * 宿主能力一律**本地结构化声明**,不 import 官方包(rc 接口会无声变);\n * `t` 席位由宿主渲染器按注册项的 `locale:` 声明合成进组件 props。\n */\nimport { createStyleKit } from \"dsh-plugin-core/design\";\nimport { setStyleKit } from \"dsh-plugin-core/ui\";\nimport { createElement as h } from \"react\";\nimport { BoardHome } from \"./board-home\";\nimport {\n\ten,\n\tfallbackTranslate,\n\tinterpolateTranslate,\n\ttype LocaleKey,\n\ttype Translate,\n\tzh,\n} from \"./locales\";\nimport { LedgerIcon } from \"./ui\";\n\n// 核心控件样式设施:id 插件内唯一(多插件同页互不覆盖);控件首次渲染时 ensureControls() 挂载。\nsetStyleKit(createStyleKit({ id: \"dsh-task-ledger\" }));\n\n/** 命名空间(settings / locale / 面板 id 同名,便于对应)。 */\n/** 模块级 t 席位(侧栏 label 渲染期求值用;绑不上就回落键名,绝不上界面)。 */\nlet runtimeT: Translate = (key) => key;\n\nconst NS = \"dsh-task-ledger\";\n/** `main` 槽的 key(非 `conversation` ⇒ 不绑 Session)。 */\nconst PANEL_ID = NS;\n\n/** 浏览器插件上下文:只声明本文件实际用到的服务面。 */\ninterface ClientContext {\n\tinject(deps: readonly string[], callback: (ctx: ClientContext) => void): void;\n\teffect(setup: () => void): void;\n\tlocale?: {\n\t\tregister(\n\t\t\tns: string,\n\t\t\tdictionaries: Record<string, Record<string, string>>,\n\t\t): void;\n\t\t/** 绑一份无参 t(侧栏 label 在渲染期求值,拿不到组件 props 的 t 席位)。 */\n\t\tbind(ns: string): Translate;\n\t};\n\tlayout?: {\n\t\tselectPanel(panelId: string | null): void;\n\t};\n\tslots: {\n\t\tinject(slot: string, factory: () => () => void): () => void;\n\t\tregister(options: Record<string, unknown>, component: unknown): () => void;\n\t};\n}\n\n/** 宿主没给 t 席位时的兜底(键名绝不上界面)。 */\nconst t: Translate = interpolateTranslate(\n\t(key: LocaleKey, params?: Record<string, string | number>) =>\n\t\tfallbackTranslate(key, params),\n);\n\nexport function apply(ctx: ClientContext): void {\n\t// ① 字典注册(宿主语言切换 ⇒ 渲染器换 t 引用 ⇒ 整页重渲染)\n\tctx.inject([\"locale\"], (localeCtx) => {\n\t\tctx.effect(() => localeCtx.locale?.register(NS, { zh, en }));\n\t\t// 模块级 t 席位:`sidebar.panellist` 的 label 由侧栏在渲染期求值,拿不到组件 props 的 t\n\t\ttry {\n\t\t\truntimeT = localeCtx.locale?.bind(NS) ?? runtimeT;\n\t\t} catch {\n\t\t\t/* 保持键名兜底 */\n\t\t}\n\t});\n\n\t// ② 布局服务:浮标点开整页 / 整页返回会话\n\tlet selectPanel: (id: string | null) => void = () => {};\n\tctx.inject([\"layout\"], (sub) => {\n\t\tconst layout = sub.layout;\n\t\tif (layout !== undefined)\n\t\t\tselectPanel = (id) => {\n\t\t\t\tlayout.selectPanel(id);\n\t\t\t};\n\t});\n\n\t// ③ 槽位注册(只依赖 slots,自成一块:locale / layout 缺席也不该让入口消失)\n\tctx.inject([\"slots\"], (sub) => {\n\t\t// 左侧入口:侧栏面板条目(list 槽)。**行按钮、点击、激活态全由侧栏 / 布局服务托管**,\n\t\t// 组件只画图标;id 必须与 main 槽的 key 一致(同一 MainPanelId)。\n\t\t// 事实见 external/client-ui-layout.md §一/§二(0.2.0-rc.2 亲验)。\n\t\tsub.slots.inject(\"sidebar.panellist\", () =>\n\t\t\tsub.slots.register(\n\t\t\t\t{\n\t\t\t\t\tname: \"sidebar.panellist\",\n\t\t\t\t\tid: PANEL_ID,\n\t\t\t\t\torder: 30,\n\t\t\t\t\tlabel: () => runtimeT(\"panelTitle\"),\n\t\t\t\t\tlocale: NS,\n\t\t\t\t},\n\t\t\t\t(props: { size?: number }) => h(LedgerIcon, { size: props.size ?? 18 }),\n\t\t\t),\n\t\t);\n\t\tsub.slots.inject(\"main\", () =>\n\t\t\tsub.slots.register(\n\t\t\t\t{ name: \"main\", key: PANEL_ID, locale: NS },\n\t\t\t\t(props: { t?: Translate }) =>\n\t\t\t\t\th(BoardHome, {\n\t\t\t\t\t\tt: props.t ?? t,\n\t\t\t\t\t\tonBack: () => {\n\t\t\t\t\t\t\tselectPanel(null);\n\t\t\t\t\t\t},\n\t\t\t\t\t}),\n\t\t\t),\n\t\t);\n\t});\n}\n"],"ignoreList":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36],"mappings":"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"}