[{"data":1,"prerenderedAt":644},["ShallowReactive",2],{"navigation_docs":3,"-guide-repo":102,"-guide-repo-surround":639},[4,82,87,92,97],{"title":5,"icon":6,"path":7,"stem":8,"children":9},"指南","i-lucide-list-tree","\u002Fguide","1.guide",[10,14,19,24,29,34,39,44,48,53,58,63,68,73,77],{"title":11,"path":7,"stem":12,"icon":13},"指南总览","1.guide\u002Findex","i-lucide-map",{"title":15,"path":16,"stem":17,"icon":18},"快速开始","\u002Fguide\u002Fquick-start","1.guide\u002F1.quick-start","i-lucide-rocket",{"title":20,"path":21,"stem":22,"icon":23},"键盘导航与可访问性","\u002Fguide\u002Fkeyboard","1.guide\u002F10.keyboard","i-lucide-keyboard",{"title":25,"path":26,"stem":27,"icon":28},"类型化 createTypedOkrTree","\u002Fguide\u002Ftyped","1.guide\u002F11.typed","i-lucide-type",{"title":30,"path":31,"stem":32,"icon":33},"Vue Devtools 面板","\u002Fguide\u002Fdevtools","1.guide\u002F12.devtools","i-lucide-wrench",{"title":35,"path":36,"stem":37,"icon":38},"需要注意的行为","\u002Fguide\u002Fbehavior","1.guide\u002F13.behavior","i-lucide-triangle-alert",{"title":40,"path":41,"stem":42,"icon":43},"仓库与本地开发","\u002Fguide\u002Frepo","1.guide\u002F14.repo","i-lucide-folder-git-2",{"title":45,"path":46,"stem":47},"Demo 总览（可交互）","\u002Fguide\u002Fdemos","1.guide\u002F2.demos",{"title":49,"path":50,"stem":51,"icon":52},"自定义节点内容","\u002Fguide\u002Fnode-content","1.guide\u002F3.node-content","i-lucide-layout-template",{"title":54,"path":55,"stem":56,"icon":57},"受控状态与方法","\u002Fguide\u002Fcontrolled","1.guide\u002F4.controlled","i-lucide-sliders-horizontal",{"title":59,"path":60,"stem":61,"icon":62},"复选框与拖拽","\u002Fguide\u002Finteraction","1.guide\u002F5.interaction","i-lucide-mouse-pointer-click",{"title":64,"path":65,"stem":66,"icon":67},"懒加载子节点","\u002Fguide\u002Flazy","1.guide\u002F6.lazy","i-lucide-layers",{"title":69,"path":70,"stem":71,"icon":72},"虚拟滚动 virtual","\u002Fguide\u002Fvirtual","1.guide\u002F7.virtual","i-lucide-scan",{"title":74,"path":75,"stem":76,"icon":72},"画布缩放 OkrTreeViewport","\u002Fguide\u002Fviewport","1.guide\u002F8.viewport",{"title":78,"path":79,"stem":80,"icon":81},"多树根对齐 OkrTreeGroup","\u002Fguide\u002Fgroup","1.guide\u002F9.group","i-lucide-network",{"title":83,"path":84,"stem":85,"icon":86},"主题与样式定制","\u002Ftheme","2.theme","i-lucide-palette",{"title":88,"path":89,"stem":90,"icon":91},"API","\u002Fapi","3.api","i-lucide-braces",{"title":93,"path":94,"stem":95,"icon":96},"与 vue-okr-tree 的差异（迁移说明）","\u002Fmigration","4.migration","i-lucide-arrow-right-left",{"title":98,"path":99,"stem":100,"icon":101},"更新日志","\u002Fchangelog","5.changelog","i-lucide-history",{"id":103,"title":40,"body":104,"description":632,"extension":633,"links":634,"meta":635,"navigation":636,"path":41,"seo":637,"stem":42,"__hash__":638},"docs\u002F1.guide\u002F14.repo.md",{"type":105,"value":106,"toc":626},"minimark",[107,111,326,330,433,436,560,581,584,622],[108,109,110],"h2",{"id":110},"目录结构",[112,113,118],"pre",{"className":114,"code":115,"language":116,"meta":117,"style":117},"language-bash shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","vue3-okr-tree\u002F\n├─ src\u002Flib\u002Fokr-tree\u002F         # 库本体\n│  ├─ OkrTree.vue            # 容器：props \u002F defineExpose \u002F 配置同步 \u002F 键盘导航\n│  ├─ OkrTreeNode.vue        # 递归节点：渲染、交互、ARIA\n│  ├─ OkrTreeGroup.vue       # 多树根对齐\n│  ├─ OkrTreeViewport.vue    # 画布缩放平移与导出\n│  ├─ model\u002F                 # 框架无关的树模型（TreeStore \u002F TreeNode \u002F util \u002F transition.css）\n│  ├─ style.css              # 组件样式（全部限定在 .org-chart-container 内）\n│  ├─ viewport.ts            # clampZoom \u002F computeFit \u002F renderToDataUrl 等纯函数\n│  └─ context.ts \u002F node-content.ts \u002F use-reduced-motion.ts\n├─ shared\u002Fapi.ts             # API 表单一来源\n├─ playground\u002F               # 可交互 Demo 站（24 个用例，文档站内嵌同一批组件）\n├─ docs-site\u002F          # 文档站（本页，Docus\u002FNuxt layer）\n├─ tests\u002F                    # Vitest 单测 + Playwright 视觉回归 + SSR 冒烟\n├─ scripts\u002F                  # gen-readme-api \u002F post-build \u002F verify-dist \u002F benchmark 等\n└─ docs\u002F                     # requirements \u002F roadmap \u002F release-guide \u002F acceptance（仓库内文档，不发布）\n","bash","",[119,120,121,130,144,159,172,185,198,211,224,237,259,270,281,292,303,314],"code",{"__ignoreMap":117},[122,123,126],"span",{"class":124,"line":125},"line",1,[122,127,129],{"class":128},"sBMFI","vue3-okr-tree\u002F\n",[122,131,133,136,140],{"class":124,"line":132},2,[122,134,135],{"class":128},"├─",[122,137,139],{"class":138},"sfazB"," src\u002Flib\u002Fokr-tree\u002F",[122,141,143],{"class":142},"sHwdD","         # 库本体\n",[122,145,147,150,153,156],{"class":124,"line":146},3,[122,148,149],{"class":128},"│",[122,151,152],{"class":138},"  ├─",[122,154,155],{"class":138}," OkrTree.vue",[122,157,158],{"class":142},"            # 容器：props \u002F defineExpose \u002F 配置同步 \u002F 键盘导航\n",[122,160,162,164,166,169],{"class":124,"line":161},4,[122,163,149],{"class":128},[122,165,152],{"class":138},[122,167,168],{"class":138}," OkrTreeNode.vue",[122,170,171],{"class":142},"        # 递归节点：渲染、交互、ARIA\n",[122,173,175,177,179,182],{"class":124,"line":174},5,[122,176,149],{"class":128},[122,178,152],{"class":138},[122,180,181],{"class":138}," OkrTreeGroup.vue",[122,183,184],{"class":142},"       # 多树根对齐\n",[122,186,188,190,192,195],{"class":124,"line":187},6,[122,189,149],{"class":128},[122,191,152],{"class":138},[122,193,194],{"class":138}," OkrTreeViewport.vue",[122,196,197],{"class":142},"    # 画布缩放平移与导出\n",[122,199,201,203,205,208],{"class":124,"line":200},7,[122,202,149],{"class":128},[122,204,152],{"class":138},[122,206,207],{"class":138}," model\u002F",[122,209,210],{"class":142},"                 # 框架无关的树模型（TreeStore \u002F TreeNode \u002F util \u002F transition.css）\n",[122,212,214,216,218,221],{"class":124,"line":213},8,[122,215,149],{"class":128},[122,217,152],{"class":138},[122,219,220],{"class":138}," style.css",[122,222,223],{"class":142},"              # 组件样式（全部限定在 .org-chart-container 内）\n",[122,225,227,229,231,234],{"class":124,"line":226},9,[122,228,149],{"class":128},[122,230,152],{"class":138},[122,232,233],{"class":138}," viewport.ts",[122,235,236],{"class":142},"            # clampZoom \u002F computeFit \u002F renderToDataUrl 等纯函数\n",[122,238,240,242,245,248,251,254,256],{"class":124,"line":239},10,[122,241,149],{"class":128},[122,243,244],{"class":138},"  └─",[122,246,247],{"class":138}," context.ts",[122,249,250],{"class":138}," \u002F",[122,252,253],{"class":138}," node-content.ts",[122,255,250],{"class":138},[122,257,258],{"class":138}," use-reduced-motion.ts\n",[122,260,262,264,267],{"class":124,"line":261},11,[122,263,135],{"class":128},[122,265,266],{"class":138}," shared\u002Fapi.ts",[122,268,269],{"class":142},"             # API 表单一来源\n",[122,271,273,275,278],{"class":124,"line":272},12,[122,274,135],{"class":128},[122,276,277],{"class":138}," playground\u002F",[122,279,280],{"class":142},"               # 可交互 Demo 站（24 个用例，文档站内嵌同一批组件）\n",[122,282,284,286,289],{"class":124,"line":283},13,[122,285,135],{"class":128},[122,287,288],{"class":138}," docs-site\u002F",[122,290,291],{"class":142},"          # 文档站（本页，Docus\u002FNuxt layer）\n",[122,293,295,297,300],{"class":124,"line":294},14,[122,296,135],{"class":128},[122,298,299],{"class":138}," tests\u002F",[122,301,302],{"class":142},"                    # Vitest 单测 + Playwright 视觉回归 + SSR 冒烟\n",[122,304,306,308,311],{"class":124,"line":305},15,[122,307,135],{"class":128},[122,309,310],{"class":138}," scripts\u002F",[122,312,313],{"class":142},"                  # gen-readme-api \u002F post-build \u002F verify-dist \u002F benchmark 等\n",[122,315,317,320,323],{"class":124,"line":316},16,[122,318,319],{"class":128},"└─",[122,321,322],{"class":138}," docs\u002F",[122,324,325],{"class":142},"                     # requirements \u002F roadmap \u002F release-guide \u002F acceptance（仓库内文档，不发布）\n",[108,327,329],{"id":328},"关键设计三份真源","关键设计：三份真源",[331,332,333,349],"table",{},[334,335,336],"thead",{},[337,338,339,343,346],"tr",{},[340,341,342],"th",{},"真源",[340,344,345],{},"位置",[340,347,348],{},"谁在消费",[350,351,352,382,407],"tbody",{},[337,353,354,358,363],{},[355,356,357],"td",{},"API 表",[355,359,360],{},[119,361,362],{},"shared\u002Fapi.ts",[355,364,365,366,369,370,373,374,377,378,381],{},"文档站 ",[119,367,368],{},"\u003CApiDoc>","、Playground API 页、README 的分组概览（",[119,371,372],{},"pnpm gen:readme"," 生成）；表与 ",[119,375,376],{},"defineExpose"," 由 ",[119,379,380],{},"tests\u002Fapi-surface.spec.ts"," 断言不漂移",[337,383,384,387,396],{},[355,385,386],{},"样式",[355,388,389,392,393],{},[119,390,391],{},"src\u002Flib\u002Fokr-tree\u002Fstyle.css"," + ",[119,394,395],{},"model\u002Ftransition.css",[355,397,398,399,402,403,406],{},"库产物 ",[119,400,401],{},"dist\u002Fstyle.css","（单文件）；连接线的几何取值多处相互咬合，改任何一项都可能产生亚像素漂移，所以外观定制走 ",[119,404,405],{},"--okr-*"," 变量而不是改样式",[337,408,409,412,419],{},[355,410,411],{},"DOM 类名与结构",[355,413,414,415,418],{},"组件模板里的 ",[119,416,417],{},"org-chart-*"," 类名",[355,420,421,424,425,428,429,432],{},[119,422,423],{},"OkrTreeGroup"," 的测量选择器（",[119,426,427],{},"OkrTreeGroup.vue:53-54","）、",[119,430,431],{},"getVisibleNodes"," 的可见性判定、视觉回归基线都按类名查询，因此 DOM 结构是对外契约的一部分",[108,434,435],{"id":435},"常用命令",[112,437,440],{"className":114,"code":438,"filename":439,"language":116,"meta":117,"style":117},"pnpm install\npnpm dev              # Demo 站（引用 src 源码）\npnpm test             # Vitest 单测\npnpm typecheck        # vue-tsc\npnpm lint             # ESLint\npnpm build            # 库构建 → dist\u002F\npnpm verify:dist      # 用 dist 产物做挂载冒烟\npnpm verify:package   # publint + attw 包发布体检\npnpm size             # size-limit 体积预算\npnpm test:visual      # Playwright 视觉回归 + 浏览器性能基线\npnpm docs:dev         # 文档站（本页）\npnpm gen:readme       # 从 shared\u002Fapi.ts 重新生成 README 的 API 概览\n",">_ Terminal",[119,441,442,450,460,470,480,490,500,510,520,530,540,550],{"__ignoreMap":117},[122,443,444,447],{"class":124,"line":125},[122,445,446],{"class":128},"pnpm",[122,448,449],{"class":138}," install\n",[122,451,452,454,457],{"class":124,"line":132},[122,453,446],{"class":128},[122,455,456],{"class":138}," dev",[122,458,459],{"class":142},"              # Demo 站（引用 src 源码）\n",[122,461,462,464,467],{"class":124,"line":146},[122,463,446],{"class":128},[122,465,466],{"class":138}," test",[122,468,469],{"class":142},"             # Vitest 单测\n",[122,471,472,474,477],{"class":124,"line":161},[122,473,446],{"class":128},[122,475,476],{"class":138}," typecheck",[122,478,479],{"class":142},"        # vue-tsc\n",[122,481,482,484,487],{"class":124,"line":174},[122,483,446],{"class":128},[122,485,486],{"class":138}," lint",[122,488,489],{"class":142},"             # ESLint\n",[122,491,492,494,497],{"class":124,"line":187},[122,493,446],{"class":128},[122,495,496],{"class":138}," build",[122,498,499],{"class":142},"            # 库构建 → dist\u002F\n",[122,501,502,504,507],{"class":124,"line":200},[122,503,446],{"class":128},[122,505,506],{"class":138}," verify:dist",[122,508,509],{"class":142},"      # 用 dist 产物做挂载冒烟\n",[122,511,512,514,517],{"class":124,"line":213},[122,513,446],{"class":128},[122,515,516],{"class":138}," verify:package",[122,518,519],{"class":142},"   # publint + attw 包发布体检\n",[122,521,522,524,527],{"class":124,"line":226},[122,523,446],{"class":128},[122,525,526],{"class":138}," size",[122,528,529],{"class":142},"             # size-limit 体积预算\n",[122,531,532,534,537],{"class":124,"line":239},[122,533,446],{"class":128},[122,535,536],{"class":138}," test:visual",[122,538,539],{"class":142},"      # Playwright 视觉回归 + 浏览器性能基线\n",[122,541,542,544,547],{"class":124,"line":261},[122,543,446],{"class":128},[122,545,546],{"class":138}," docs:dev",[122,548,549],{"class":142},"         # 文档站（本页）\n",[122,551,552,554,557],{"class":124,"line":272},[122,553,446],{"class":128},[122,555,556],{"class":138}," gen:readme",[122,558,559],{"class":142},"       # 从 shared\u002Fapi.ts 重新生成 README 的 API 概览\n",[561,562,563,564,566,567,570,571,573,574,576,577,580],"p",{},"改了 ",[119,565,362],{}," 或 ",[119,568,569],{},"src\u002F"," 的 ",[119,572,376],{}," 之后要跑 ",[119,575,372],{},"——README 的 API 段是生成物，不手改（仓库根 ",[119,578,579],{},"AGENTS.md"," 记了这条约定）。",[108,582,583],{"id":583},"发布",[561,585,586,587,570,590,593,594,597,598,601,602,605,606,609,610,613,614,621],{},"更新 ",[119,588,589],{},"package.json",[119,591,592],{},"version"," 与 ",[119,595,596],{},"CHANGELOG.md"," → 提交 → ",[119,599,600],{},"git tag v1.x.x && git push origin v1.x.x","，",[119,603,604],{},"release.yml"," 跑完门禁后 ",[119,607,608],{},"npm publish --provenance"," 并创建 GitHub Release。完整步骤与前置配置见仓库 ",[119,611,612],{},"docs\u002Frelease-guide.md","。版本号自 1.13.0 起与姊妹包 ",[615,616,620],"a",{"href":617,"rel":618},"https:\u002F\u002Freact-okr-tree.baiwumm.com",[619],"nofollow","react-okr-tree"," 锁步发布。",[623,624,625],"style",{},"html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":117,"searchDepth":132,"depth":132,"links":627},[628,629,630,631],{"id":110,"depth":132,"text":110},{"id":328,"depth":132,"text":329},{"id":435,"depth":132,"text":435},{"id":583,"depth":132,"text":583},"仓库目录结构、三份真源与本地开发命令","md",null,{},{"icon":43},{"title":40,"description":632},"9awlTY0UnR-tbj_ZrfT0glOQfYkEXOtmImtzN_ZOf9I",[640,642],{"title":35,"path":36,"stem":37,"description":641,"icon":38,"children":-1},"回写源数据、node-key 缺失、冻结 \u002F 只读数据等边界行为清单",{"title":45,"path":46,"stem":47,"description":643,"children":-1},"与 Playground 同一批组件源码的可交互用例集",1790437331290]