@allbluecn/web-app 0.18.2 → 0.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (761) hide show
  1. package/package.json +66 -51
  2. package/src/__tests__/components/auth/auth-layout.test.tsx +13 -1
  3. package/src/__tests__/{knowledge-public → knowledge/public}/canonical-id.test.ts +1 -1
  4. package/src/__tests__/{knowledge-public → knowledge/public}/favicon.test.ts +1 -1
  5. package/src/__tests__/{knowledge-public → knowledge/public}/github-sync.test.ts +1 -1
  6. package/src/__tests__/{knowledge-public → knowledge/public}/share-merge.test.ts +7 -7
  7. package/src/__tests__/security/xss-sanitize.test.ts +9 -8
  8. package/src/components/ai/__tests__/chat-thread-id-stability.test.tsx +125 -0
  9. package/src/components/ai/ai-chat-prompt.tsx +8 -2
  10. package/src/components/ai/ai-prompt-input/index.tsx +2 -1
  11. package/src/components/ai/global-harness-sidebar/__tests__/global-ai-prompts.test.ts +1 -2
  12. package/src/components/ai/global-harness-sidebar/index.tsx +22 -10
  13. package/src/components/bug/__tests__/board-subgroups.test.tsx +512 -0
  14. package/src/components/bug/__tests__/board-view.test.tsx +350 -0
  15. package/src/components/bug/__tests__/bug-list-loading-defer.test.tsx +85 -0
  16. package/src/components/bug/__tests__/bug-toolbar.test.tsx +7 -1
  17. package/src/components/bug/__tests__/comment-reactions.test.tsx +182 -0
  18. package/src/components/bug/__tests__/date-and-lightbox.test.tsx +96 -0
  19. package/src/components/bug/__tests__/export-entry.test.tsx +217 -0
  20. package/src/components/bug/__tests__/filters-compat.test.tsx +157 -0
  21. package/src/components/bug/__tests__/fix-request-race.test.tsx +396 -0
  22. package/src/components/bug/__tests__/peek-modes.test.tsx +365 -0
  23. package/src/components/bug/__tests__/saved-views.test.tsx +309 -0
  24. package/src/components/bug/__tests__/story-bugs-panel.test.tsx +146 -0
  25. package/src/components/bug/__tests__/subgroup-header.test.tsx +150 -0
  26. package/src/components/bug/__tests__/toolbar-shell.test.tsx +369 -0
  27. package/src/components/bug/__tests__/use-paged-bug-groups.test.tsx +58 -0
  28. package/src/components/bug/__tests__/view-type.test.tsx +247 -0
  29. package/src/components/bug/bug-list-view.tsx +310 -13
  30. package/src/components/bug/bug-panel-header.tsx +84 -8
  31. package/src/components/bug/bug-toolbar.tsx +268 -116
  32. package/src/components/bug/create-bug-dialog.tsx +1 -1
  33. package/src/components/bug/detail/__tests__/activity-timeline.test.tsx +1 -0
  34. package/src/components/bug/detail/__tests__/bug-detail-collab.test.tsx +236 -0
  35. package/src/components/bug/detail/__tests__/repro-report-card.test.tsx +2 -1
  36. package/src/components/bug/detail/activity-timeline.tsx +1 -1
  37. package/src/components/bug/detail/bug-detail-body.tsx +316 -18
  38. package/src/components/bug/detail/comment-item.tsx +7 -2
  39. package/src/components/bug/detail/comment-reactions.tsx +138 -0
  40. package/src/components/bug/detail/error-context.tsx +29 -9
  41. package/src/components/bug/detail/props-section.tsx +31 -3
  42. package/src/components/bug/detail/repro-report-card.tsx +1 -1
  43. package/src/components/bug/display/constants.ts +4 -2
  44. package/src/components/bug/display/display-dropdown.tsx +76 -280
  45. package/src/components/bug/display/types.ts +24 -8
  46. package/src/components/bug/display/use-paged-bug-groups.ts +183 -32
  47. package/src/components/bug/filters/{filter-value-input.tsx → field-configs.tsx} +218 -106
  48. package/src/components/bug/filters/index.tsx +14 -5
  49. package/src/components/bug/inline-editors/assignee-editor.tsx +2 -2
  50. package/src/components/bug/inline-editors/labels-editor.tsx +1 -1
  51. package/src/components/bug/inline-editors/severity-editor.tsx +37 -18
  52. package/src/components/bug/inline-editors/state-editor.tsx +1 -1
  53. package/src/components/bug/peek-panel.tsx +153 -35
  54. package/src/components/bug/select-bug-dialog.tsx +500 -0
  55. package/src/components/bug/story-bugs-panel.tsx +1090 -0
  56. package/src/components/bug/types.ts +9 -2
  57. package/src/components/bug/views/board-view.tsx +661 -0
  58. package/src/components/bug/views/bug-list/batch-toolbar.tsx +25 -34
  59. package/src/components/bug/views/bug-list/group.tsx +28 -13
  60. package/src/components/bug/views/bug-list/index.tsx +223 -59
  61. package/src/components/bug/views/bug-list/row.tsx +7 -1
  62. package/src/components/bug/views/create-view-dialog.tsx +160 -0
  63. package/src/components/bug/views/view-list-section.tsx +140 -0
  64. package/src/components/bug/views/view-selector-button.tsx +145 -0
  65. package/src/components/bug/views/view-switcher.tsx +8 -6
  66. package/src/components/bug/views/view-types.ts +162 -0
  67. package/src/components/collab/__tests__/activity-attribution.test.tsx +211 -0
  68. package/src/components/collab/__tests__/canvas-collab-panel.test.tsx +118 -0
  69. package/src/components/collab/__tests__/collab-presence-header.test.tsx +335 -0
  70. package/src/components/collab/__tests__/entity-presence-badge.test.tsx +226 -0
  71. package/src/components/collab/activity-attribution.tsx +221 -0
  72. package/src/components/collab/canvas-collab-panel.tsx +104 -0
  73. package/src/components/collab/collab-presence-header.tsx +220 -0
  74. package/src/components/collab/entity-presence-badge.tsx +130 -0
  75. package/src/components/collab/field-editing-pill.tsx +137 -0
  76. package/src/components/command/command-palette.tsx +6 -6
  77. package/src/components/design/canvas/document/__tests__/canvas-tree-fixture-snapshot.ts +589 -0
  78. package/src/components/design/canvas/document/__tests__/canvas-tree-reconcile.test.ts +159 -0
  79. package/src/components/design/canvas/panels/toolbar.tsx +3 -2
  80. package/src/components/design/canvas/plugins/presence/__tests__/canvas-collab-wiring.test.tsx +660 -0
  81. package/src/components/design/canvas/plugins/presence/__tests__/layout.test.ts +292 -0
  82. package/src/components/design/canvas/plugins/presence/__tests__/presence-overlay.test.tsx +139 -0
  83. package/src/components/design/canvas/plugins/presence/layout.ts +222 -0
  84. package/src/components/design/canvas/plugins/presence/presence-layer.tsx +353 -0
  85. package/src/components/design/canvas/plugins/presence/presence-overlay.tsx +155 -0
  86. package/src/components/design/canvas/plugins/presence/viewer-badge.tsx +80 -0
  87. package/src/components/design/canvas/react/__tests__/hooks.test.tsx +4 -4
  88. package/src/components/design/editor/collaboration/__tests__/design-agent-panel-regenerate.test.tsx +3 -1
  89. package/src/components/design/editor/collaboration/__tests__/design-agent-panel-stream.test.tsx +3 -1
  90. package/src/components/design/editor/collaboration/design-agent-panel.tsx +3 -0
  91. package/src/components/design/editor/collaboration/design-comment-review-panel.tsx +5 -5
  92. package/src/components/design/editor/dashboard/create-design-dialog.tsx +1 -1
  93. package/src/components/design/editor/dashboard/design-dashboard.tsx +1 -10
  94. package/src/components/design/editor/layout/__tests__/collab-param-wiring.test.tsx +153 -0
  95. package/src/components/design/editor/layout/__tests__/no-page-save-toast.test.tsx +8 -0
  96. package/src/components/design/editor/layout/design-editor-layout.tsx +28 -1
  97. package/src/components/design/editor/layout/design-navigation.tsx +0 -4
  98. package/src/components/design/editor/layout/hooks/__tests__/use-design-auto-save-collab.test.tsx +130 -0
  99. package/src/components/design/editor/layout/hooks/use-design-auto-save.ts +18 -1
  100. package/src/components/design/editor/share/share-comment-panel.tsx +37 -20
  101. package/src/components/design/editor/share/share-layout.tsx +3 -0
  102. package/src/components/design/editor/share/share-nav-bar.tsx +7 -1
  103. package/src/components/design/editor/share/share-theme-toggle.tsx +10 -15
  104. package/src/components/design/editor/tiptap/node/paragraph-node/paragraph-node.scss +1 -1
  105. package/src/components/harness/__tests__/composer-draft.test.ts +126 -0
  106. package/src/components/harness/composer/composer-editor.tsx +64 -6
  107. package/src/components/harness/composer/harness-composer.tsx +1 -1
  108. package/src/components/harness/harness-layout.tsx +1 -1
  109. package/src/components/harness/harness-workbench-page.tsx +6 -1
  110. package/src/components/harness/turn-group.tsx +1 -1
  111. package/src/components/hotkeys/shortcut-badge.tsx +4 -4
  112. package/src/components/knowledge/dialog/knowledge-form-dialog.tsx +1 -1
  113. package/src/components/knowledge/editor/__tests__/knowledge-doc-editor-collab.test.tsx +542 -0
  114. package/src/components/knowledge/editor/doc-header.tsx +7 -49
  115. package/src/components/knowledge/editor/knowledge-doc-editor.tsx +264 -51
  116. package/src/components/knowledge/editor/mindmap-doc-editor.tsx +3 -19
  117. package/src/components/knowledge/knowledge-homepage.tsx +3 -3
  118. package/src/components/knowledge/knowledge-toolbar.tsx +8 -8
  119. package/src/components/{knowledge-public → knowledge/public}/bookmark-form-dialog.tsx +4 -4
  120. package/src/components/{knowledge-public → knowledge/public}/knowledge-card.tsx +1 -15
  121. package/src/components/{knowledge-public → knowledge/public}/knowledge-form-dialog.tsx +9 -9
  122. package/src/components/{knowledge-public → knowledge/public}/legal-compliance-editor.tsx +35 -28
  123. package/src/components/{knowledge-public → knowledge/public}/sharers-avatar-group.tsx +3 -2
  124. package/src/components/layout/layout-responsive-provider.tsx +79 -0
  125. package/src/components/layout/sidebar-03/__tests__/presence-avatar-stack.test.tsx +148 -0
  126. package/src/components/layout/sidebar-03/app-sidebar.tsx +9 -3
  127. package/src/components/layout/sidebar-03/index.tsx +19 -4
  128. package/src/components/layout/sidebar-03/nav-main.tsx +28 -10
  129. package/src/components/layout/sidebar-03/presence-avatar-stack.tsx +112 -0
  130. package/src/components/layout/sidebar-03/user-menu.tsx +3 -3
  131. package/src/components/project/create-project-dialog.tsx +1 -1
  132. package/src/components/project/invite-member-dialog.tsx +1 -1
  133. package/src/components/project/project-activity-list.tsx +2 -2
  134. package/src/components/project/project-member-manager.tsx +2 -2
  135. package/src/components/reui/__tests__/kanban-drop-indicator.test.ts +88 -0
  136. package/src/components/reui/__tests__/kanban-keyboard.test.ts +262 -0
  137. package/src/components/reui/event-calendar/event-calendar-agenda-view.tsx +236 -0
  138. package/src/components/reui/event-calendar/event-calendar-content.tsx +80 -0
  139. package/src/components/reui/event-calendar/event-calendar-dnd.tsx +1062 -0
  140. package/src/components/reui/event-calendar/event-calendar-event.tsx +555 -0
  141. package/src/components/reui/event-calendar/event-calendar-i18n.tsx +291 -0
  142. package/src/components/reui/event-calendar/event-calendar-lib.tsx +677 -0
  143. package/src/components/reui/event-calendar/event-calendar-month-view.tsx +1287 -0
  144. package/src/components/reui/event-calendar/event-calendar-nav.tsx +615 -0
  145. package/src/components/reui/event-calendar/event-calendar-recurrence.tsx +592 -0
  146. package/src/components/reui/event-calendar/event-calendar-resource-view.tsx +810 -0
  147. package/src/components/reui/event-calendar/event-calendar-time-grid.tsx +1366 -0
  148. package/src/components/reui/event-calendar/event-calendar-types.tsx +240 -0
  149. package/src/components/reui/event-calendar/event-calendar.tsx +1916 -0
  150. package/src/components/reui/gantt/__tests__/gantt-row-window.test.ts +243 -0
  151. package/src/components/reui/gantt/__tests__/gantt-view-virtualize.test.tsx +243 -0
  152. package/src/components/reui/gantt/gantt-bar.tsx +439 -0
  153. package/src/components/reui/gantt/gantt-dnd.tsx +1000 -0
  154. package/src/components/reui/gantt/gantt-i18n.tsx +287 -0
  155. package/src/components/reui/gantt/gantt-lib.tsx +695 -0
  156. package/src/components/reui/gantt/gantt-nav.tsx +446 -0
  157. package/src/components/reui/gantt/gantt-recurrence.tsx +402 -0
  158. package/src/components/reui/gantt/gantt-row-window.ts +119 -0
  159. package/src/components/reui/gantt/gantt-types.tsx +283 -0
  160. package/src/components/reui/gantt/gantt-view.tsx +4466 -0
  161. package/src/components/reui/gantt/gantt.tsx +1822 -0
  162. package/src/components/reui/gantt/use-gantt-row-window.ts +159 -0
  163. package/src/components/reui/icon-stack.tsx +90 -0
  164. package/src/components/reui/kanban-keyboard.ts +268 -0
  165. package/src/components/reui/kanban.tsx +1227 -0
  166. package/src/components/settings/personal-team/account/account-client.tsx +3 -2
  167. package/src/components/settings/personal-team/team/invitation-cards/invitation-history-list.tsx +5 -5
  168. package/src/components/settings/personal-team/team/team-client.tsx +2 -1
  169. package/src/components/settings/personal-team/team/team-member-list.tsx +4 -4
  170. package/src/components/share/share-presence-bar.tsx +182 -0
  171. package/src/components/shared-kit/auth/auth-client.ts +5 -0
  172. package/src/components/shared-kit/avatars/__tests__/avatar-shape.test.ts +44 -0
  173. package/src/components/shared-kit/avatars/__tests__/user-avatar.test.tsx +46 -0
  174. package/src/components/{tags/tags-collection.ts → shared-kit/avatars/avatar-shape.ts} +14 -20
  175. package/src/components/shared-kit/avatars/notion-avatar.tsx +62 -11
  176. package/src/components/shared-kit/avatars/user-avatar.tsx +7 -4
  177. package/src/components/shared-kit/list-kit/__tests__/batch-toolbar-shell.test.tsx +133 -0
  178. package/src/components/shared-kit/list-kit/__tests__/frozen-header.test.ts +89 -0
  179. package/src/components/shared-kit/list-kit/__tests__/level-badge.test.tsx +85 -0
  180. package/src/components/shared-kit/list-kit/__tests__/toolbar-shell.test.tsx +178 -0
  181. package/src/components/shared-kit/list-kit/batch-toolbar-shell.tsx +111 -0
  182. package/src/components/shared-kit/list-kit/csv-download.ts +46 -0
  183. package/src/components/shared-kit/list-kit/display/__tests__/dropdown.test.tsx +215 -0
  184. package/src/components/shared-kit/list-kit/display/dropdown.tsx +582 -0
  185. package/src/components/shared-kit/list-kit/display/types.ts +64 -0
  186. package/src/components/shared-kit/list-kit/display/values.ts +60 -0
  187. package/src/components/shared-kit/list-kit/filters/__tests__/create-filters-module.test.tsx +181 -0
  188. package/src/components/shared-kit/list-kit/filters/__tests__/types.test.ts +133 -0
  189. package/src/components/shared-kit/list-kit/filters/index.tsx +757 -0
  190. package/src/components/shared-kit/list-kit/filters/types.ts +68 -0
  191. package/src/components/shared-kit/list-kit/frozen-header.ts +45 -0
  192. package/src/components/shared-kit/list-kit/icon-semantics.ts +50 -0
  193. package/src/components/shared-kit/list-kit/kanban/__tests__/drop-layout.test.ts +139 -0
  194. package/src/components/shared-kit/list-kit/kanban/__tests__/frozen-header.test.ts +111 -0
  195. package/src/components/shared-kit/list-kit/kanban/__tests__/instance-key.test.ts +130 -0
  196. package/src/components/shared-kit/list-kit/kanban/__tests__/kanban-board-view.test.tsx +901 -0
  197. package/src/components/shared-kit/list-kit/kanban/__tests__/manual-order.test.ts +35 -0
  198. package/src/components/shared-kit/list-kit/kanban/drop-commit.ts +212 -0
  199. package/src/components/shared-kit/list-kit/kanban/drop-layout.ts +98 -0
  200. package/src/components/shared-kit/list-kit/kanban/frozen-header.ts +88 -0
  201. package/src/components/shared-kit/list-kit/kanban/instance-key.ts +83 -0
  202. package/src/components/shared-kit/list-kit/kanban/kanban-board-view.tsx +1414 -0
  203. package/src/components/shared-kit/list-kit/kanban/manual-order.ts +39 -0
  204. package/src/components/shared-kit/list-kit/level-badge.tsx +71 -0
  205. package/src/components/shared-kit/list-kit/toolbar-shell.tsx +103 -0
  206. package/src/components/shared-kit/loading/__tests__/use-deferred-flag.test.tsx +115 -0
  207. package/src/components/shared-kit/loading/use-deferred-flag.ts +35 -0
  208. package/src/components/shared-kit/peek/dock-slot.ts +62 -0
  209. package/src/components/shared-kit/peek/peek-mode.ts +34 -0
  210. package/src/components/shared-kit/theme/animated-theme-toggler.tsx +13 -7
  211. package/src/components/shared-kit/theme/theme-toggle.tsx +7 -18
  212. package/src/components/shared-kit/views/view-icon.tsx +49 -0
  213. package/src/components/story/__tests__/peek-panel-patch-sync.test.tsx +215 -0
  214. package/src/components/story/__tests__/story-list-loading-defer.test.tsx +88 -0
  215. package/src/components/story/__tests__/story-list-view-peek-sync.test.tsx +242 -0
  216. package/src/components/story/__tests__/story-list-view-restore.test.tsx +45 -3
  217. package/src/components/story/__tests__/story-list-view-ssr.test.tsx +0 -1
  218. package/src/components/story/ai/__tests__/action-registry.test.ts +11 -11
  219. package/src/components/story/ai/action-registry.ts +5 -7
  220. package/src/components/story/ai/handlers/stream-text.ts +1 -3
  221. package/src/components/story/ai/story-ai-toolbar.tsx +58 -16
  222. package/src/components/story/ai/use-toolbar-overflow.ts +4 -7
  223. package/src/components/story/columns.tsx +2 -2
  224. package/src/components/story/constants.ts +17 -1
  225. package/src/components/story/create-story-dialog.tsx +8 -7
  226. package/src/components/story/detail/__tests__/associated-attachments-panel.test.tsx +38 -4
  227. package/src/components/story/detail/__tests__/categories.test.tsx +52 -26
  228. package/src/components/story/detail/__tests__/story-collab.test.tsx +897 -0
  229. package/src/components/story/detail/activity-tabs.tsx +5 -4
  230. package/src/components/story/detail/activity-timeline.tsx +15 -3
  231. package/src/components/story/detail/comment-input.tsx +2 -2
  232. package/src/components/story/detail/comment-item.tsx +6 -3
  233. package/src/components/story/detail/comment-thread.tsx +1 -0
  234. package/src/components/story/detail/reaction-bar.tsx +1 -1
  235. package/src/components/story/detail/story-detail-body.tsx +501 -76
  236. package/src/components/story/detail/story-detail-toolbar/__tests__/related-test-cases.test.tsx +173 -10
  237. package/src/components/story/detail/story-detail-toolbar/associated-attachments-panel.tsx +144 -8
  238. package/src/components/story/detail/story-detail-toolbar/categories.tsx +82 -38
  239. package/src/components/story/detail/story-detail-toolbar/children.tsx +254 -174
  240. package/src/components/story/detail/story-detail-toolbar/dependency-panel.tsx +140 -58
  241. package/src/components/story/detail/story-detail-toolbar/index.tsx +613 -0
  242. package/src/components/story/detail/story-detail-toolbar/related-test-cases.tsx +1010 -87
  243. package/src/components/story/detail/story-detail-toolbar/scroll-hint.tsx +57 -0
  244. package/src/components/story/detail/story-detail-toolbar/use-panel-frozen-groups.ts +97 -0
  245. package/src/components/story/detail/story-properties.tsx +9 -5
  246. package/src/components/story/display/__tests__/display-dropdown-helpers.test.ts +17 -1
  247. package/src/components/story/display/__tests__/display-dropdown.test.tsx +9 -0
  248. package/src/components/story/display/__tests__/flatten-story-groups.test.ts +42 -0
  249. package/src/components/story/display/__tests__/group-fields.test.ts +81 -1
  250. package/src/components/story/display/__tests__/group-resolver.test.ts +153 -1
  251. package/src/components/story/display/__tests__/use-collapsed-subgroups.test.ts +158 -0
  252. package/src/components/story/display/__tests__/use-display-options.test.ts +32 -3
  253. package/src/components/story/display/__tests__/use-fit-count.test.ts +198 -0
  254. package/src/components/story/display/__tests__/use-paged-story-groups.test.ts +77 -3
  255. package/src/components/story/display/constants.ts +23 -2
  256. package/src/components/story/display/display-dropdown.tsx +95 -397
  257. package/src/components/story/display/flatten-story-groups.ts +39 -0
  258. package/src/components/story/display/group-fields.ts +32 -1
  259. package/src/components/story/display/group-resolver.tsx +128 -5
  260. package/src/components/story/display/types.ts +23 -42
  261. package/src/components/story/display/use-collapsed-subgroups.ts +109 -0
  262. package/src/components/story/display/use-display-options.ts +21 -5
  263. package/src/components/story/display/use-fit-count.ts +124 -0
  264. package/src/components/story/display/use-paged-story-groups.ts +174 -31
  265. package/src/components/story/filters/field-configs.tsx +263 -0
  266. package/src/components/story/filters/index.tsx +14 -5
  267. package/src/components/story/inline-editors/__tests__/labels-editor.test.tsx +2 -0
  268. package/src/components/story/inline-editors/__tests__/priority-editor.test.tsx +15 -0
  269. package/src/components/story/inline-editors/assignee-editor.tsx +7 -5
  270. package/src/components/story/inline-editors/date-editor.tsx +7 -2
  271. package/src/components/story/inline-editors/inline-trigger.tsx +17 -4
  272. package/src/components/story/inline-editors/labels-editor.tsx +243 -35
  273. package/src/components/story/inline-editors/parent-story-editor.tsx +1 -1
  274. package/src/components/story/inline-editors/priority-editor.tsx +6 -4
  275. package/src/components/story/inline-editors/state-editor.tsx +6 -4
  276. package/src/components/story/inline-editors/story-select-dialog.tsx +56 -19
  277. package/src/components/story/peek-panel.tsx +234 -51
  278. package/src/components/story/relations/__tests__/design-select-dialog.test.tsx +131 -0
  279. package/src/components/story/relations/attachment-manage-dialog.tsx +1 -1
  280. package/src/components/story/relations/design-select-dialog.tsx +285 -0
  281. package/src/components/story/relations/knowledge-select-dialog.tsx +3 -3
  282. package/src/components/story/relations/link-manage-dialog.tsx +2 -2
  283. package/src/components/story/story-list-view.tsx +175 -17
  284. package/src/components/story/story-panel-header.tsx +18 -11
  285. package/src/components/story/story-toolbar.tsx +177 -126
  286. package/src/components/story/transfer-story-popover.tsx +1 -1
  287. package/src/components/story/types.ts +11 -2
  288. package/src/components/story/views/__tests__/calendar-view.test.tsx +262 -0
  289. package/src/components/story/views/__tests__/kanban-drop-subgroup.test.ts +68 -0
  290. package/src/components/story/views/__tests__/kanban-peek-sync.test.tsx +184 -0
  291. package/src/components/story/views/__tests__/kanban-view-membership-sync.test.tsx +179 -0
  292. package/src/components/story/views/__tests__/timeline-view.test.tsx +453 -0
  293. package/src/components/story/views/__tests__/view-icon.test.tsx +45 -0
  294. package/src/components/story/views/__tests__/view-types.test.ts +0 -8
  295. package/src/components/story/views/calendar/__tests__/mappers.test.ts +201 -0
  296. package/src/components/story/views/calendar/__tests__/slot-draft.test.ts +78 -0
  297. package/src/components/story/views/calendar/drag-blocked.ts +41 -0
  298. package/src/components/story/views/calendar/i18n.ts +91 -0
  299. package/src/components/story/views/calendar/mappers.ts +119 -0
  300. package/src/components/story/views/calendar/slot-draft.ts +48 -0
  301. package/src/components/story/views/calendar-view.tsx +490 -223
  302. package/src/components/story/views/create-view-dialog.tsx +6 -6
  303. package/src/components/story/views/kanban-view.tsx +618 -0
  304. package/src/components/story/views/{__tests__ → story-list/__tests__}/use-flat-rows.test.ts +1 -1
  305. package/src/components/story/views/story-list/batch-preview-dialog.tsx +3 -3
  306. package/src/components/story/views/story-list/batch-toolbar.tsx +17 -34
  307. package/src/components/story/views/story-list/group.tsx +4 -2
  308. package/src/components/story/views/story-list/index.tsx +142 -34
  309. package/src/components/story/views/story-list/row.tsx +4 -0
  310. package/src/components/story/views/{use-flat-rows.ts → story-list/use-flat-rows.ts} +2 -2
  311. package/src/components/story/views/timeline/__tests__/mappers.test.ts +742 -0
  312. package/src/components/story/views/timeline/__tests__/sentinel-geometry.test.ts +76 -0
  313. package/src/components/story/views/timeline/__tests__/use-date-commit.test.tsx +372 -0
  314. package/src/components/story/views/timeline/i18n.ts +96 -0
  315. package/src/components/story/views/timeline/mappers.ts +506 -0
  316. package/src/components/story/views/timeline/sentinel-geometry.ts +43 -0
  317. package/src/components/story/views/timeline/use-date-commit.ts +169 -0
  318. package/src/components/story/views/timeline-view.tsx +593 -222
  319. package/src/components/story/views/view-list-section.tsx +4 -4
  320. package/src/components/story/views/view-selector-button.tsx +9 -10
  321. package/src/components/story/views/view-switcher.tsx +7 -1
  322. package/src/components/story/views/view-types.ts +1 -5
  323. package/src/components/testcase/__tests__/batch-toolbar.test.tsx +245 -0
  324. package/src/components/testcase/__tests__/board-view.test.tsx +241 -0
  325. package/src/components/testcase/__tests__/case-row.test.tsx +24 -10
  326. package/src/components/testcase/__tests__/constants.test.ts +151 -0
  327. package/src/components/testcase/__tests__/create-dialog-scope.test.tsx +173 -0
  328. package/src/components/testcase/__tests__/detail-properties.test.tsx +19 -0
  329. package/src/components/testcase/__tests__/display-options.test.tsx +154 -0
  330. package/src/components/testcase/__tests__/export-entry.test.tsx +279 -0
  331. package/src/components/testcase/__tests__/filters.test.tsx +280 -0
  332. package/src/components/testcase/__tests__/list-view-scope.test.tsx +290 -0
  333. package/src/components/testcase/__tests__/list-view.test.tsx +552 -7
  334. package/src/components/testcase/__tests__/manual-move.test.ts +69 -0
  335. package/src/components/testcase/__tests__/peek-panel.test.tsx +89 -8
  336. package/src/components/testcase/__tests__/toolbar.test.tsx +302 -0
  337. package/src/components/testcase/__tests__/view-fallback.test.tsx +272 -0
  338. package/src/components/testcase/__tests__/view-management.test.tsx +179 -0
  339. package/src/components/testcase/ai/generate-dialog.tsx +1 -1
  340. package/src/components/testcase/constants.ts +83 -0
  341. package/src/components/testcase/create-testcase-dialog.tsx +76 -8
  342. package/src/components/testcase/detail/__tests__/select-cases-dialog.test.tsx +163 -0
  343. package/src/components/testcase/detail/case-detail-body.tsx +311 -30
  344. package/src/components/testcase/detail/select-cases-dialog.tsx +465 -0
  345. package/src/components/testcase/detail/story-link-editor.tsx +1 -1
  346. package/src/components/testcase/display/display-dropdown.tsx +147 -0
  347. package/src/components/testcase/display/field-configs.ts +80 -0
  348. package/src/components/testcase/display/use-testcase-display-options.ts +59 -0
  349. package/src/components/testcase/filters/field-configs.tsx +748 -0
  350. package/src/components/testcase/filters/index.tsx +35 -127
  351. package/src/components/testcase/inline-editors/assignee-editor.tsx +6 -6
  352. package/src/components/testcase/inline-editors/folder-editor.tsx +9 -9
  353. package/src/components/testcase/inline-editors/priority-editor.tsx +47 -31
  354. package/src/components/testcase/inline-editors/state-editor.tsx +14 -12
  355. package/src/components/testcase/inline-editors/type-editor.tsx +31 -20
  356. package/src/components/testcase/list/case-row.tsx +60 -2
  357. package/src/components/testcase/list/grouped-list.tsx +3 -2
  358. package/src/components/testcase/list-view.tsx +633 -137
  359. package/src/components/testcase/peek-panel.tsx +69 -11
  360. package/src/components/testcase/plans/plan-list.tsx +6 -1
  361. package/src/components/testcase/step-editor.tsx +34 -3
  362. package/src/components/testcase/testcase-toolbar.tsx +349 -94
  363. package/src/components/testcase/views/batch-toolbar.tsx +203 -0
  364. package/src/components/testcase/views/board-view.tsx +546 -0
  365. package/src/components/testcase/views/create-view-dialog.tsx +26 -14
  366. package/src/components/testcase/views/move.ts +56 -0
  367. package/src/components/testcase/views/view-selector-button.tsx +82 -30
  368. package/src/components/testcase/views/view-switcher.tsx +12 -5
  369. package/src/components/testcase/views/view-types.ts +50 -27
  370. package/src/components/tiptap/mindmap/lib/__tests__/shortcuts.test.ts +5 -4
  371. package/src/components/tiptap/mindmap/lib/shortcuts.ts +4 -3
  372. package/src/components/tiptap/node/doc-card-node-view.tsx +2 -1
  373. package/src/components/tiptap/notion-like/editor-extensions.ts +231 -0
  374. package/src/components/tiptap/notion-like/notion-like-editor.tsx +29 -156
  375. package/src/components/tiptap/ui/ai-menu/ai-menu.tsx +6 -1
  376. package/src/components/tiptap/ui/doc-reference-interaction/doc-reference-interaction.tsx +2 -1
  377. package/src/components/ui/checkbox.tsx +4 -4
  378. package/src/components/ui/popover.tsx +1 -1
  379. package/src/components/workspace/dialogs/edit-workspace-dialog.tsx +1 -1
  380. package/src/components/workspace/kb/workspace-kb-manage-dialog.tsx +1 -1
  381. package/src/components/workspace/kb/workspace-quick-doc-dialog.tsx +1 -1
  382. package/src/components/workspace/members/workspace-member-item.tsx +2 -2
  383. package/src/components/workspace/members/workspace-members-manager.tsx +2 -2
  384. package/src/config/sidebar-routes.tsx +11 -13
  385. package/src/design-engine/document/serialize-leafer-json.ts +2 -1
  386. package/src/design-engine/engine/__tests__/engine-split.test.ts +1 -1
  387. package/src/design-engine/engine/__tests__/engine.test.ts +20 -0
  388. package/src/design-engine/engine/app.ts +5 -0
  389. package/src/design-engine/engine/engine-base.ts +17 -0
  390. package/src/design-engine/engine/engine-doc.ts +32 -0
  391. package/src/hooks/__tests__/use-commands.test.tsx +17 -5
  392. package/src/hooks/use-commands.ts +4 -4
  393. package/src/hooks/use-toolbar-search.ts +7 -2
  394. package/src/lib/__tests__/datetime-local.test.ts +46 -0
  395. package/src/lib/__tests__/datetime.test.ts +7 -0
  396. package/src/lib/__tests__/layout-responsive.test.ts +123 -0
  397. package/src/lib/__tests__/sidebar-utils.test.ts +4 -4
  398. package/src/lib/ai/story-ai-stream.ts +1 -1
  399. package/src/lib/ai/use-selected-model.ts +15 -5
  400. package/src/lib/changelog/sdk-versions.ts +22 -22
  401. package/src/lib/collab/__tests__/bindings-fields.test.ts +496 -0
  402. package/src/lib/collab/__tests__/bindings-steps.test.ts +332 -0
  403. package/src/lib/collab/__tests__/presence-store.test.ts +414 -0
  404. package/src/lib/collab/__tests__/provider-handle-contract.test.ts +89 -0
  405. package/src/lib/collab/__tests__/provider.test.ts +504 -0
  406. package/src/lib/collab/__tests__/use-presence-list-refresh.test.tsx +309 -0
  407. package/src/lib/collab/__tests__/use-presence-report.test.ts +356 -0
  408. package/src/lib/collab/__tests__/use-share-presence.test.ts +555 -0
  409. package/src/lib/collab/__tests__/user-color.test.ts +53 -0
  410. package/src/lib/collab/bindings/__tests__/canvas-local.test.ts +583 -0
  411. package/src/lib/collab/bindings/__tests__/canvas-presence.test.ts +378 -0
  412. package/src/lib/collab/bindings/__tests__/canvas-remote.test.ts +454 -0
  413. package/src/lib/collab/bindings/__tests__/canvas-tree-perf.test.ts +134 -0
  414. package/src/lib/collab/bindings/canvas-local.ts +415 -0
  415. package/src/lib/collab/bindings/canvas-presence.ts +420 -0
  416. package/src/lib/collab/bindings/canvas-remote.ts +226 -0
  417. package/src/lib/collab/bindings/fields.ts +463 -0
  418. package/src/lib/collab/bindings/steps.ts +332 -0
  419. package/src/lib/collab/env.ts +33 -0
  420. package/src/lib/collab/module-map.ts +131 -0
  421. package/src/lib/collab/presence-store.ts +350 -0
  422. package/src/lib/collab/provider.ts +378 -0
  423. package/src/lib/collab/use-collab-doc.ts +100 -0
  424. package/src/lib/collab/use-presence-list-refresh.ts +142 -0
  425. package/src/lib/collab/use-presence-report.ts +176 -0
  426. package/src/lib/collab/use-self-profile-broadcast.ts +113 -0
  427. package/src/lib/collab/use-share-presence.ts +561 -0
  428. package/src/lib/collab/user-color.ts +40 -0
  429. package/src/lib/collections/index.ts +0 -1
  430. package/src/lib/collections/reference/bookmark-categories-collection.ts +1 -1
  431. package/src/lib/commands/__tests__/registry.test.ts +2 -5
  432. package/src/lib/commands/registry.ts +0 -3
  433. package/src/lib/commands/types.ts +1 -1
  434. package/src/lib/datetime.ts +20 -3
  435. package/src/lib/hooks/__tests__/use-synced-state.test.tsx +54 -0
  436. package/src/lib/hooks/use-story-panel-open.ts +134 -0
  437. package/src/lib/hooks/use-synced-state.ts +17 -0
  438. package/src/lib/hotkeys/__tests__/registry.test.ts +1 -1
  439. package/src/lib/hotkeys/registry.ts +0 -3
  440. package/src/lib/layout-responsive.ts +140 -0
  441. package/src/lib/pacer.ts +10 -1
  442. package/src/lib/peek-dock.ts +32 -0
  443. package/src/lib/plugin-runtime/__tests__/plugin-tool-schema-parity.test.ts +140 -0
  444. package/src/lib/plugin-runtime/plugin-client-tools.ts +28 -46
  445. package/src/lib/plugin-runtime/plugin-tool-defs.ts +152 -0
  446. package/src/lib/project-module-meta.ts +1 -8
  447. package/src/lib/rate-limit.ts +15 -6
  448. package/src/lib/sanitize.ts +122 -10
  449. package/src/lib/share-events.ts +20 -11
  450. package/src/lib/sidebar-utils.ts +1 -1
  451. package/src/lib/theme/__tests__/theme-mode.test.ts +96 -0
  452. package/src/lib/theme/theme-mode.ts +77 -0
  453. package/src/paraglide/messages/_index.js +5312 -1591
  454. package/src/paraglide/messages/en.js +1880 -685
  455. package/src/paraglide/messages/zh.js +1877 -682
  456. package/src/providers/index.tsx +4 -1
  457. package/src/providers/theme-mode-provider.tsx +135 -0
  458. package/src/routeTree.gen.ts +78 -101
  459. package/src/routes/$lang/docs/$/route.lazy.tsx +7 -2
  460. package/src/routes/-tests/chat-body-validation.test.ts +61 -3
  461. package/src/routes/__tests__/-edition-routing.test.tsx +12 -8
  462. package/src/routes/_nav/-components/nav-not-found.tsx +2 -2
  463. package/src/routes/_nav/bugs/$bugId/route.lazy.tsx +16 -2
  464. package/src/routes/_nav/bugs/$bugId/route.tsx +11 -2
  465. package/src/routes/_nav/dashboard/-components/avatar-group.tsx +2 -2
  466. package/src/routes/_nav/knowledge/$kbId/doc/$docId/route.lazy.tsx +31 -17
  467. package/src/routes/_nav/knowledge/$kbId/doc/$docId/route.tsx +12 -1
  468. package/src/routes/_nav/knowledge/$kbId/index.lazy.tsx +4 -2
  469. package/src/routes/_nav/knowledge/$kbId/route.lazy.tsx +7 -3
  470. package/src/routes/_nav/knowledge/bookmarks/$id.lazy.tsx +6 -6
  471. package/src/routes/_nav/knowledge/bookmarks/index.lazy.tsx +10 -10
  472. package/src/routes/_nav/knowledge/compliance/$id.lazy.tsx +9 -9
  473. package/src/routes/_nav/knowledge/compliance/edit/$id.lazy.tsx +1 -1
  474. package/src/routes/_nav/knowledge/compliance/index.lazy.tsx +8 -8
  475. package/src/routes/_nav/knowledge/dictionaries/$id.lazy.tsx +4 -4
  476. package/src/routes/_nav/knowledge/dictionaries/index.lazy.tsx +6 -6
  477. package/src/routes/_nav/knowledge/index.lazy.tsx +1 -1
  478. package/src/routes/_nav/knowledge/laws/$id.lazy.tsx +9 -9
  479. package/src/routes/_nav/knowledge/laws/edit/$id.lazy.tsx +1 -1
  480. package/src/routes/_nav/knowledge/laws/index.lazy.tsx +11 -11
  481. package/src/routes/_nav/knowledge/summary/index.lazy.tsx +1 -1
  482. package/src/routes/_nav/projects/$projectId/index.lazy.tsx +14 -6
  483. package/src/routes/_nav/route.lazy.tsx +11 -6
  484. package/src/routes/_nav/settings/account/route.tsx +3 -2
  485. package/src/routes/_nav/stories/$storyId/route.lazy.tsx +52 -8
  486. package/src/routes/_nav/stories/$storyId/route.tsx +11 -0
  487. package/src/routes/_nav/stories/-components/story-detail-skeleton.tsx +1 -1
  488. package/src/{components/tags/pages/tag-detail-page.tsx → routes/_nav/tasks/$taskId/route.lazy.tsx} +20 -10
  489. package/src/routes/_nav/tasks/$taskId/route.tsx +43 -0
  490. package/src/routes/_nav/tasks/-components/ai-task-detail.tsx +307 -0
  491. package/src/routes/_nav/tasks/-components/ai-task-list.tsx +217 -0
  492. package/src/routes/_nav/tasks/-components/ai-task-status-badge.tsx +46 -0
  493. package/src/routes/_nav/tasks/-components/assigned-list.tsx +157 -0
  494. package/src/routes/_nav/tasks/-components/create-ai-task-dialog.tsx +228 -0
  495. package/src/routes/_nav/tasks/-components/source-ai-exec-dialog.tsx +175 -0
  496. package/src/routes/_nav/tasks/-components/task-constants.ts +115 -0
  497. package/src/routes/_nav/tasks/-components/use-task-filter.ts +64 -0
  498. package/src/routes/_nav/tasks/-tests/create-ai-task-dialog.test.tsx +175 -0
  499. package/src/routes/_nav/tasks/-tests/task-filter.test.ts +134 -0
  500. package/src/routes/_nav/tasks/-tests/task-styles.test.tsx +119 -0
  501. package/src/routes/_nav/tasks/index.lazy.tsx +114 -0
  502. package/src/routes/_nav/tasks/index.tsx +47 -0
  503. package/src/routes/_nav/{tags → tasks}/route.tsx +3 -3
  504. package/src/routes/_nav/test-cases/$caseId/route.lazy.tsx +3 -1
  505. package/src/routes/_nav/test-cases/$caseId/route.tsx +11 -2
  506. package/src/routes/api/chat.ts +23 -19
  507. package/src/routes/api/design/prototype/route.ts +2 -4
  508. package/src/routes/{_nav/acceptance-criteria/route.tsx → api/internal/collab-reindex.ts} +11 -8
  509. package/src/routes/api/knowledge/sync-github.ts +1 -1
  510. package/src/routes/design-files/$projectId/$artboardId/$filename.ts +9 -0
  511. package/src/routes/invite/$token/route.lazy.tsx +2 -2
  512. package/src/routes/share/$versionId/route.lazy.tsx +8 -0
  513. package/src/routes/share/compliance/$id/route.lazy.tsx +2 -2
  514. package/src/routes/share/compliance/$id/route.tsx +1 -1
  515. package/src/routes/share/law/$id/route.lazy.tsx +2 -2
  516. package/src/routes/share/law/$id/route.tsx +1 -1
  517. package/src/server/__tests__/bug-groups-two-level.test.ts +263 -0
  518. package/src/server/__tests__/builtin-project.test.ts +45 -1
  519. package/src/server/__tests__/csv-export.test.ts +319 -0
  520. package/src/server/__tests__/share-version.test.ts +7 -2
  521. package/src/server/__tests__/task-assigned-query.test.ts +232 -0
  522. package/src/server/__tests__/task-context-builder.test.ts +175 -0
  523. package/src/server/__tests__/task-executor.test.ts +349 -0
  524. package/src/server/__tests__/task-priority-map.test.ts +41 -0
  525. package/src/server/__tests__/task-serverfn-crud.test.ts +639 -0
  526. package/src/server/__tests__/task-serverfn-queries.test.ts +403 -0
  527. package/src/server/__tests__/testcase-board.test.ts +301 -0
  528. package/src/server/__tests__/testcase-bulk.test.ts +155 -0
  529. package/src/server/__tests__/testcase-list-scope.test.ts +215 -0
  530. package/src/server/ai-gateway/__tests__/chat-handler-prompt-key.test.ts +106 -0
  531. package/src/server/ai-gateway/__tests__/chat-stream-builder-sandbox.test.ts +9 -3
  532. package/src/server/ai-gateway/__tests__/conformance.test.ts +4 -3
  533. package/src/server/ai-gateway/adapter.ts +4 -2
  534. package/src/server/ai-gateway/chat-handler.ts +13 -5
  535. package/src/server/ai-gateway/chat-stream-builder.ts +12 -7
  536. package/src/server/ai-gateway/sandbox/__tests__/harness-sandbox.test.ts +88 -0
  537. package/src/server/ai-gateway/sandbox/harness-sandbox.ts +1 -1
  538. package/src/server/ai-gateway/story-handler.ts +7 -2
  539. package/src/server/ai-gateway/tools/plugin-lifecycle-defs.ts +8 -99
  540. package/src/server/ai-gateway/tools/plugin-tools.ts +6 -10
  541. package/src/server/ai-task/assigned-query.ts +167 -0
  542. package/src/server/ai-task/context-builder.ts +182 -0
  543. package/src/server/ai-task/executor.ts +296 -0
  544. package/src/server/ai-task/priority-map.ts +37 -0
  545. package/src/server/ai-task/types.ts +15 -0
  546. package/src/server/bug-report/__tests__/report-handler.test.ts +55 -4
  547. package/src/server/bug-report/report-handler.ts +54 -8
  548. package/src/server/builtin-project.ts +24 -0
  549. package/src/server/cloudflare/prisma-wasm-base64-stub.ts +5 -0
  550. package/src/server/collab/__tests__/collab-permissions.test.ts +412 -0
  551. package/src/server/collab/__tests__/knowledge-additions.test.ts +121 -0
  552. package/src/server/collab/__tests__/reindex-endpoint.test.ts +168 -0
  553. package/src/server/collab/__tests__/resolve.test.ts +249 -0
  554. package/src/server/collab/__tests__/touch-snapshot.test.ts +58 -0
  555. package/src/server/collab/__tests__/write-guard-sdk.test.ts +501 -0
  556. package/src/server/collab/__tests__/write-guard.test.ts +373 -0
  557. package/src/server/collab/knowledge-additions.ts +37 -0
  558. package/src/server/collab/reindex-endpoint.ts +75 -0
  559. package/src/server/collab/resolve.ts +122 -0
  560. package/src/server/collab/seed.ts +408 -0
  561. package/src/server/collab/ticket-utils.ts +107 -0
  562. package/src/server/collab/touch-snapshot.ts +55 -0
  563. package/src/server/collab/write-guard.ts +258 -0
  564. package/src/server/collab-permissions.ts +248 -0
  565. package/src/server/csv.ts +61 -0
  566. package/src/server/{knowledge-public → knowledge/public}/github-sync.ts +12 -2
  567. package/src/server/{knowledge-public → knowledge/public}/share-merge.ts +31 -8
  568. package/src/server/lib/__tests__/sequence-number-retry.test.ts +160 -0
  569. package/src/server/lib/rate-limit.ts +13 -2
  570. package/src/server/lib/sequence-number-retry.ts +85 -0
  571. package/src/server/mcp/__tests__/tools.test.ts +10 -0
  572. package/src/server/mcp/tools.ts +26 -2
  573. package/src/server/middlewares/auth-rate-limit.ts +18 -9
  574. package/src/server/notifications/event-bus.ts +3 -0
  575. package/src/server/serverFns/__tests__/collab-snapshot.test.ts +665 -0
  576. package/src/server/serverFns/__tests__/collab.test.ts +459 -0
  577. package/src/server/serverFns/__tests__/knowledge-delete.test.ts +167 -0
  578. package/src/server/serverFns/__tests__/ownership-merge.test.ts +34 -2
  579. package/src/server/serverFns/__tests__/read-write-merge.test.ts +2 -2
  580. package/src/server/serverFns/__tests__/story-crud-archive-detail.test.ts +12 -2
  581. package/src/server/serverFns/__tests__/story-crud.test.ts +51 -11
  582. package/src/server/serverFns/__tests__/story-tree.test.ts +66 -34
  583. package/src/server/serverFns/__tests__/story-types.test.ts +14 -9
  584. package/src/server/serverFns/__tests__/update-bug-guard.test.ts +325 -0
  585. package/src/server/serverFns/__tests__/update-document-guard.test.ts +285 -0
  586. package/src/server/serverFns/__tests__/update-page-guard.test.ts +276 -0
  587. package/src/server/serverFns/__tests__/update-story-guard.test.ts +436 -0
  588. package/src/server/serverFns/__tests__/update-testcase-guard.test.ts +293 -0
  589. package/src/server/serverFns/bug/__tests__/bug-comments.test.ts +25 -0
  590. package/src/server/serverFns/bug/__tests__/bug-crud.test.ts +315 -15
  591. package/src/server/serverFns/bug/__tests__/bug-groups.test.ts +36 -18
  592. package/src/server/serverFns/bug/__tests__/bug-list-query.test.ts +21 -0
  593. package/src/server/serverFns/bug/__tests__/bug-reactions.test.ts +335 -0
  594. package/src/server/serverFns/bug/__tests__/bug-reorder.test.ts +165 -0
  595. package/src/server/serverFns/bug/__tests__/bug-story.test.ts +4 -1
  596. package/src/server/serverFns/bug/bug-comments.ts +5 -0
  597. package/src/server/serverFns/bug/bug-crud.ts +321 -72
  598. package/src/server/serverFns/bug/bug-display-options.ts +11 -0
  599. package/src/server/serverFns/bug/bug-export.ts +137 -0
  600. package/src/server/serverFns/bug/bug-group-query.ts +16 -5
  601. package/src/server/serverFns/bug/bug-groups.ts +39 -15
  602. package/src/server/serverFns/bug/bug-list-query.ts +8 -1
  603. package/src/server/serverFns/bug/bug-reactions.ts +123 -0
  604. package/src/server/serverFns/bug/bug-reorder.ts +64 -0
  605. package/src/server/serverFns/bug/bug-story-bulk.ts +280 -0
  606. package/src/server/serverFns/bug/bug-story.ts +47 -39
  607. package/src/server/serverFns/bug/index.ts +6 -0
  608. package/src/server/serverFns/collab-presence.ts +119 -0
  609. package/src/server/serverFns/collab-snapshot.ts +201 -0
  610. package/src/server/serverFns/collab.ts +153 -0
  611. package/src/server/serverFns/design/__tests__/designs.test.ts +0 -2
  612. package/src/server/serverFns/design/designs.ts +0 -64
  613. package/src/server/serverFns/design/detail.ts +36 -2
  614. package/src/server/serverFns/design/pages.ts +73 -10
  615. package/src/server/serverFns/iteration/iteration-crud.ts +25 -1
  616. package/src/server/serverFns/{knowledge-public → knowledge/public}/bookmarks/create.ts +3 -3
  617. package/src/server/serverFns/{knowledge-public → knowledge/public}/bookmarks/detail.ts +2 -2
  618. package/src/server/serverFns/{knowledge-public → knowledge/public}/bookmarks/list.ts +3 -2
  619. package/src/server/serverFns/{knowledge-public → knowledge/public}/bookmarks/refresh-favicon.ts +1 -1
  620. package/src/server/serverFns/{knowledge-public → knowledge/public}/bookmarks/share.ts +1 -1
  621. package/src/server/serverFns/{knowledge-public → knowledge/public}/bookmarks/sync-github.ts +1 -1
  622. package/src/server/serverFns/{knowledge-public → knowledge/public}/bookmarks/update.ts +5 -4
  623. package/src/server/serverFns/{knowledge-public → knowledge/public}/compliance/create.ts +1 -1
  624. package/src/server/serverFns/{knowledge-public → knowledge/public}/compliance/detail.ts +2 -2
  625. package/src/server/serverFns/{knowledge-public → knowledge/public}/compliance/list.ts +3 -2
  626. package/src/server/serverFns/{knowledge-public → knowledge/public}/compliance/share.ts +1 -1
  627. package/src/server/serverFns/{knowledge-public → knowledge/public}/compliance/update.ts +3 -2
  628. package/src/server/serverFns/{knowledge-public → knowledge/public}/dictionary/create.ts +1 -1
  629. package/src/server/serverFns/{knowledge-public → knowledge/public}/dictionary/detail.ts +2 -2
  630. package/src/server/serverFns/{knowledge-public → knowledge/public}/dictionary/list.ts +3 -2
  631. package/src/server/serverFns/{knowledge-public → knowledge/public}/dictionary/share.ts +1 -1
  632. package/src/server/serverFns/{knowledge-public → knowledge/public}/dictionary/update.ts +3 -2
  633. package/src/server/serverFns/{knowledge-public → knowledge/public}/legal/create.ts +1 -1
  634. package/src/server/serverFns/{knowledge-public → knowledge/public}/legal/detail.ts +2 -2
  635. package/src/server/serverFns/{knowledge-public → knowledge/public}/legal/list.ts +3 -2
  636. package/src/server/serverFns/{knowledge-public → knowledge/public}/legal/share.ts +1 -1
  637. package/src/server/serverFns/{knowledge-public → knowledge/public}/legal/update.ts +3 -2
  638. package/src/server/serverFns/knowledge.ts +135 -19
  639. package/src/server/serverFns/project/module-overview.ts +1 -2
  640. package/src/server/serverFns/share/version.ts +7 -1
  641. package/src/server/serverFns/story/__tests__/bulk.test.ts +6 -0
  642. package/src/server/serverFns/story/__tests__/create-story-internal.test.ts +112 -3
  643. package/src/server/serverFns/story/__tests__/story-assoc.test.ts +77 -6
  644. package/src/server/serverFns/story/__tests__/story-crud-date-key.test.ts +187 -0
  645. package/src/server/serverFns/story/__tests__/story-gantt-deps.test.ts +163 -0
  646. package/src/server/serverFns/story/__tests__/story-groups.test.ts +4 -0
  647. package/src/server/serverFns/story/__tests__/story-list-query.test.ts +20 -0
  648. package/src/server/serverFns/story/__tests__/story-search.test.ts +5 -0
  649. package/src/server/serverFns/story/__tests__/story-transfer.test.ts +64 -1
  650. package/src/server/serverFns/story/index.ts +2 -2
  651. package/src/server/serverFns/story/story-assoc.ts +44 -14
  652. package/src/server/serverFns/story/story-crud/archive.ts +52 -28
  653. package/src/server/serverFns/story/story-crud/bulk.ts +14 -4
  654. package/src/server/serverFns/story/story-crud/create-story-internal.ts +39 -21
  655. package/src/server/serverFns/story/story-crud.ts +283 -116
  656. package/src/server/serverFns/story/story-dependencies.ts +31 -0
  657. package/src/server/serverFns/story/story-groups.ts +15 -11
  658. package/src/server/serverFns/story/story-list-query.ts +16 -4
  659. package/src/server/serverFns/story/story-search.ts +9 -6
  660. package/src/server/serverFns/story/story-transfer.ts +99 -42
  661. package/src/server/serverFns/story/story-tree.ts +70 -48
  662. package/src/server/serverFns/story-display-options.ts +21 -10
  663. package/src/server/serverFns/story-view.ts +2 -2
  664. package/src/server/serverFns/tasks/task-crud.ts +264 -0
  665. package/src/server/serverFns/tasks/task-queries.ts +172 -0
  666. package/src/server/serverFns/testcase/__tests__/generation.test.ts +3 -0
  667. package/src/server/serverFns/testcase/__tests__/stats.test.ts +18 -4
  668. package/src/server/serverFns/testcase/__tests__/testcase-board.test.ts +113 -0
  669. package/src/server/serverFns/testcase/__tests__/testcase-crud.test.ts +62 -14
  670. package/src/server/serverFns/testcase/__tests__/testcase-groups.test.ts +32 -10
  671. package/src/server/serverFns/testcase/bulk.ts +195 -0
  672. package/src/server/serverFns/testcase/generation.ts +10 -0
  673. package/src/server/serverFns/testcase/stats.ts +22 -8
  674. package/src/server/serverFns/testcase/testcase-board.ts +198 -0
  675. package/src/server/serverFns/testcase/testcase-crud.ts +165 -33
  676. package/src/server/serverFns/testcase/testcase-display-options.ts +166 -0
  677. package/src/server/serverFns/testcase/testcase-export.ts +125 -0
  678. package/src/server/serverFns/testcase/testcase-filter-views.ts +36 -9
  679. package/src/server/serverFns/testcase/testcase-groups.ts +27 -23
  680. package/src/server/serverFns/testcase/testcase-reorder.ts +66 -0
  681. package/src/server/story/__tests__/date-key.test.ts +57 -0
  682. package/src/server/story/date-key.ts +36 -0
  683. package/src/server/story/types.ts +3 -7
  684. package/src/server/testcase/__tests__/list-query.test.ts +269 -0
  685. package/src/server/testcase/list-query.ts +145 -0
  686. package/src/server-entry.ts +32 -0
  687. package/src/shared/bug/__tests__/constants.test.ts +44 -0
  688. package/src/shared/bug/constants.ts +37 -1
  689. package/src/start.ts +7 -2
  690. package/src/styles/globals.css +24 -3
  691. package/src/types/project.ts +2 -3
  692. package/vite.shared.ts +110 -3
  693. package/src/__tests__/tag-badge.test.tsx +0 -41
  694. package/src/components/bug/__tests__/bug-list-table.test.tsx +0 -289
  695. package/src/components/bug/bug-list-table.tsx +0 -187
  696. package/src/components/bug/columns.tsx +0 -193
  697. package/src/components/bug/filters/add-filter-dropdown.tsx +0 -70
  698. package/src/components/bug/filters/applied-filters.tsx +0 -214
  699. package/src/components/bug/filters/filter-condition.tsx +0 -151
  700. package/src/components/bug/filters/filter-row.tsx +0 -104
  701. package/src/components/bug/filters/filter-toggle.tsx +0 -61
  702. package/src/components/bug/filters/filter-types.ts +0 -146
  703. package/src/components/story/detail/story-detail-toolbar.tsx +0 -382
  704. package/src/components/story/filters/add-filter-dropdown.tsx +0 -70
  705. package/src/components/story/filters/applied-filters.tsx +0 -225
  706. package/src/components/story/filters/filter-condition.tsx +0 -152
  707. package/src/components/story/filters/filter-row.tsx +0 -116
  708. package/src/components/story/filters/filter-toggle.tsx +0 -60
  709. package/src/components/story/filters/filter-types.ts +0 -120
  710. package/src/components/story/filters/filter-value-input.tsx +0 -182
  711. package/src/components/story/views/kanban-board.tsx +0 -464
  712. package/src/components/story/views/kanban-card.tsx +0 -100
  713. package/src/components/tags/__tests__/tags.test.ts +0 -388
  714. package/src/components/tags/nav-tag.tsx +0 -121
  715. package/src/components/tags/pages/tag-settings-page.tsx +0 -32
  716. package/src/components/tags/pages/tags-index-page.tsx +0 -32
  717. package/src/components/tags/tag-badge.tsx +0 -56
  718. package/src/components/tags/tag-color-classes.ts +0 -61
  719. package/src/components/tags/tag-color-picker.tsx +0 -54
  720. package/src/components/tags/tag-components-index.ts +0 -23
  721. package/src/components/tags/tag-manager.tsx +0 -208
  722. package/src/components/tags/tag-selector.tsx +0 -164
  723. package/src/components/testcase/__tests__/table-view.test.tsx +0 -328
  724. package/src/components/testcase/plans/add-to-plan-bar.tsx +0 -64
  725. package/src/components/testcase/table/columns.tsx +0 -170
  726. package/src/components/testcase/table/table-view.tsx +0 -152
  727. package/src/lib/tag-colors.ts +0 -35
  728. package/src/routes/_nav/tags/$id/route.lazy.tsx +0 -23
  729. package/src/routes/_nav/tags/$id/route.tsx +0 -20
  730. package/src/routes/_nav/tags/index.lazy.tsx +0 -23
  731. package/src/routes/_nav/tags/index.tsx +0 -20
  732. package/src/routes/_nav/tags/settings/route.lazy.tsx +0 -23
  733. package/src/routes/_nav/tags/settings/route.tsx +0 -23
  734. package/src/server/serverFns/tags.ts +0 -138
  735. /package/src/components/{knowledge-public → knowledge/public}/bookmark-card.tsx +0 -0
  736. /package/src/components/{knowledge-public → knowledge/public}/category-icon.tsx +0 -0
  737. /package/src/components/{knowledge-public → knowledge/public}/chip-utils.ts +0 -0
  738. /package/src/components/{knowledge-public → knowledge/public}/knowledge-card-grid.tsx +0 -0
  739. /package/src/components/{knowledge-public → knowledge/public}/knowledge-filters.tsx +0 -0
  740. /package/src/components/{knowledge-public → knowledge/public}/knowledge-search-bar.tsx +0 -0
  741. /package/src/components/{knowledge-public → knowledge/public}/markdown-editor.tsx +0 -0
  742. /package/src/components/{knowledge-public → knowledge/public}/markdown-view.tsx +0 -0
  743. /package/src/components/{knowledge-public → knowledge/public}/tag-filter.tsx +0 -0
  744. /package/src/components/{story/detail → shared-kit/comments}/emoji-picker.tsx +0 -0
  745. /package/src/components/story/{schemas/story-create.ts → story-create-schema.ts} +0 -0
  746. /package/src/server/{knowledge-public → knowledge/public}/canonical-id.ts +0 -0
  747. /package/src/server/{knowledge-public → knowledge/public}/favicon.ts +0 -0
  748. /package/src/server/serverFns/{knowledge-public → knowledge/public}/bookmarks/categories.ts +0 -0
  749. /package/src/server/serverFns/{knowledge-public → knowledge/public}/bookmarks/delete.ts +0 -0
  750. /package/src/server/serverFns/{knowledge-public → knowledge/public}/bookmarks/favorite.ts +0 -0
  751. /package/src/server/serverFns/{knowledge-public → knowledge/public}/bookmarks/unshare.ts +0 -0
  752. /package/src/server/serverFns/{knowledge-public → knowledge/public}/compliance/delete.ts +0 -0
  753. /package/src/server/serverFns/{knowledge-public → knowledge/public}/compliance/public.ts +0 -0
  754. /package/src/server/serverFns/{knowledge-public → knowledge/public}/compliance/unshare.ts +0 -0
  755. /package/src/server/serverFns/{knowledge-public → knowledge/public}/dictionary/delete.ts +0 -0
  756. /package/src/server/serverFns/{knowledge-public → knowledge/public}/dictionary/unshare.ts +0 -0
  757. /package/src/server/serverFns/{knowledge-public → knowledge/public}/entity-tags.ts +0 -0
  758. /package/src/server/serverFns/{knowledge-public → knowledge/public}/favorite.ts +0 -0
  759. /package/src/server/serverFns/{knowledge-public → knowledge/public}/legal/delete.ts +0 -0
  760. /package/src/server/serverFns/{knowledge-public → knowledge/public}/legal/public.ts +0 -0
  761. /package/src/server/serverFns/{knowledge-public → knowledge/public}/legal/unshare.ts +0 -0
@@ -0,0 +1,39 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-or-later
2
+ // AllBlue - 理想之海
3
+ // Copyright (C) 2026 AllBlue Contributors
4
+ //
5
+ // This program is free software: you can redistribute it and/or modify
6
+ // it under the terms of the GNU Affero General Public License as published by
7
+ // the Free Software Foundation, either version 3 of the License, or
8
+ // (at your option) any later version.
9
+ //
10
+ // This program is distributed in the hope that it will be useful,
11
+ // but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ // GNU Affero General Public License for more details.
14
+ //
15
+ // You should have received a copy of the GNU Affero General Public License
16
+ // along with this program. If not, see <https://www.gnu.org/licenses/>.
17
+
18
+ import type { DisplayOptions } from "../display/types";
19
+
20
+ /**
21
+ * 看板拖拽落库后是否要把排序键切到「手动排序」。
22
+ *
23
+ * 看板顺序来自分组查询的排序键(story 默认 createdAt desc,testcase 缺省
24
+ * manual),拖拽只写 boardOrder。排序键不是 manual 时,落库的 boardOrder 不会
25
+ * 被读,卡片随即被排回原位(用户感知为「拖拽排序无效」)。故实际发生排序落库后
26
+ * 切换到 manual,让 boardOrder 立即生效。
27
+ *
28
+ * 参数按 string 接收(PR-7b 任务 26 起 testcase 等模块的排序键联合复用本判定,
29
+ * 不再钉 story 的 OrderKey;返回的 `{ orderBy: "manual" }` 对各模块
30
+ * Partial<DisplayOptions*> 均可赋值——"manual" 在各模块排序键集内)。
31
+ */
32
+ export function manualOrderSwitchPatch(
33
+ orderBy: DisplayOptions["orderBy"] | string,
34
+ reordered: boolean,
35
+ ): { orderBy: "manual" } | null {
36
+ if (!reordered) return null;
37
+ if (orderBy === "manual") return null;
38
+ return { orderBy: "manual" };
39
+ }
@@ -0,0 +1,71 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-or-later
2
+ // AllBlue - 理想之海
3
+ // Copyright (C) 2026 AllBlue Contributors
4
+ //
5
+ // This program is free software: you can redistribute it and/or modify
6
+ // it under the terms of the GNU Affero General Public License as published by
7
+ // the Free Software Foundation, either version 3 of the License, or
8
+ // (at your option) any later version.
9
+ //
10
+ // This program is distributed in the hope that it will be useful,
11
+ // but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ // GNU Affero General Public License for more details.
14
+ //
15
+ // You should have received a copy of the GNU Affero General Public License
16
+ // along with this program. If not, see <https://www.gnu.org/licenses/>.
17
+
18
+ import type { LucideIcon } from "lucide-react";
19
+ import { Badge } from "@/components/ui/badge";
20
+ import { cn } from "@/lib/utils";
21
+
22
+ /** 分级徽章 meta 表的一项:label 为展示文案,icon 可选,color 为完整
23
+ * Tailwind 工具类字符串(设计 §5.1:`bg-{c}-500/15 text-{c}-600 dark:text-{c}-400`) */
24
+ export interface LevelBadgeMeta {
25
+ label: string;
26
+ icon?: LucideIcon;
27
+ color: string;
28
+ }
29
+
30
+ export interface LevelBadgeProps {
31
+ /** 分级 key(如 state / priority 的 value);不在 meta 中时回退中性态 */
32
+ level: string;
33
+ /** level → 展示元数据映射,由调用方传入(纯原子,零业务耦合) */
34
+ meta: Record<string, LevelBadgeMeta>;
35
+ /** badge = 徽章形态(图标 + label + color 类);icon = 纯图标形态(仅 color 的 text 类,无背景) */
36
+ variant?: "badge" | "icon";
37
+ }
38
+
39
+ const NEUTRAL_BADGE_COLOR = "bg-muted text-muted-foreground";
40
+ const NEUTRAL_ICON_COLOR = "text-muted-foreground";
41
+
42
+ /** 从完整工具类字符串中提取字色类(含 `dark:text-*` 等带前缀变体),
43
+ * 供 icon 变体去掉 `bg-*` 背景底色、只保留字色。
44
+ * 任务 29 起导出:完整徽章 token 的 META(如 TEST_CASE_STATE_META)被
45
+ * icon-only 场景消费时统一走本函数,杜绝「图标带无圆角底色块」过渡态 */
46
+ export function extractTextColors(color: string): string {
47
+ return color
48
+ .split(/\s+/)
49
+ .filter((token) => token.includes("text-"))
50
+ .join(" ");
51
+ }
52
+
53
+ export function LevelBadge({ level, meta, variant = "badge" }: LevelBadgeProps) {
54
+ const entry = meta[level];
55
+
56
+ if (variant === "icon") {
57
+ if (!entry?.icon) return null;
58
+ const Icon = entry.icon;
59
+ const textColor = extractTextColors(entry.color) || NEUTRAL_ICON_COLOR;
60
+ return <Icon aria-hidden className={cn("size-3.5", textColor)} />;
61
+ }
62
+
63
+ const color = entry?.color ?? NEUTRAL_BADGE_COLOR;
64
+ const Icon = entry?.icon;
65
+ return (
66
+ <Badge className={cn(color)}>
67
+ {Icon && <Icon aria-hidden />}
68
+ {entry?.label ?? level}
69
+ </Badge>
70
+ );
71
+ }
@@ -0,0 +1,103 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-or-later
2
+ // AllBlue - 理想之海
3
+ // Copyright (C) 2026 AllBlue Contributors
4
+ //
5
+ // This program is free software: you can redistribute it and/or modify
6
+ // it under the terms of the GNU Affero General Public License as published by
7
+ // the Free Software Foundation, either version 3 of the License, or
8
+ // (at your option) any later version.
9
+ //
10
+ // This program is distributed in the hope that it will be useful,
11
+ // but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ // GNU Affero General Public License for more details.
14
+ //
15
+ // You should have received a copy of the GNU Affero General Public License
16
+ // along with this program. If not, see <https://www.gnu.org/licenses/>.
17
+
18
+ import { useEffect, useRef, useState, type ReactNode, type Ref } from "react";
19
+
20
+ /**
21
+ * 列表工具栏紧凑档判定 hook(行宽 <920px)。
22
+ *
23
+ * 紧凑档驱动「更多」菜单的业务件显隐(如新建需求项收纳进菜单)——菜单 portal 到
24
+ * body 后脱离 @container 祖先,容器查询类(@max-[920px])失效,必须 JS 判定。
25
+ * ref 接到被观察元素(通常经 ToolbarShell 的 rowRef 挂到三列网格行上)。
26
+ */
27
+ export function useToolbarCompact(): {
28
+ ref: React.RefObject<HTMLDivElement | null>;
29
+ compact: boolean;
30
+ } {
31
+ const ref = useRef<HTMLDivElement>(null);
32
+ const [compact, setCompact] = useState(false);
33
+ useEffect(() => {
34
+ const el = ref.current;
35
+ if (!el) return;
36
+ const ro = new ResizeObserver(() => setCompact(el.clientWidth < 920));
37
+ ro.observe(el);
38
+ return () => ro.disconnect();
39
+ }, []);
40
+ return { ref, compact };
41
+ }
42
+
43
+ export interface ToolbarShellProps {
44
+ /** 左簇业务件(项目按钮 / 视图选择器 / 总数等)。壳提供 `flex items-center gap-2` 簇容器 */
45
+ left?: ReactNode;
46
+ /** 中列搜索输入框本体(业务件:图标 + 受控 Input)。壳包降级容器
47
+ * `relative w-full min-w-30 max-w-60`——`@max-[530px]:hidden` 阈值类挂容器
48
+ * 外层,窄容器下整格隐藏不留空白(内层隐藏外层仍占满宽是反模式) */
49
+ search?: ReactNode;
50
+ /** ≤530px 的搜索降级件(story 形态:图标按钮 + Popover 内 autoFocus 输入框),
51
+ * 与 search 同列并排;显隐类(默认 hidden、`@max-[530px]:flex`)由消费方自带 */
52
+ searchFallback?: ReactNode;
53
+ /** 右簇业务件(筛选 / 显示 / 视图切换 / 新建 / 更多)。壳提供
54
+ * `flex shrink-0 items-center gap-2 justify-self-end` 簇容器 */
55
+ right?: ReactNode;
56
+ /** 工具栏行下方附属区(筛选行 / 已应用过滤 / 对话框等),直排于外层 flex-col */
57
+ below?: ReactNode;
58
+ /** 外部观察句柄:接 `useToolbarCompact()` 返回的 ref,壳挂到三列网格行元素上 */
59
+ rowRef?: Ref<HTMLDivElement>;
60
+ }
61
+
62
+ /**
63
+ * 列表工具栏三列网格壳(story 工具栏布局抽取,list-kit 共享)。
64
+ *
65
+ * 三列网格:两侧 1fr 等宽 + 中列 0.5fr → 中列中心恒等于行中心(两侧等宽时
66
+ * 1.25 × 单元宽 = 行宽一半),项目/视图名称长度变化不会移动搜索框;
67
+ * 空间不足时三列按比例收缩(中列下限 min-w-30,超过 15rem 由输入框 max-w-60 封顶),
68
+ * 窄到放不下时(<530px)输入框隐藏、由 searchFallback 图标按钮接管。
69
+ *
70
+ * 降级阶梯(消费方业务件自带断点类,壳保证 @container 祖先):
71
+ * `@max-[530px]` 搜索 → 图标按钮 + Popover / `@max-[780px]` 项目按钮降级 /
72
+ * `@max-[920px]` 新建收纳「更多」(portal 后容器查询失效,配 useToolbarCompact
73
+ * JS 判定)/ `@max-[1000px]` 视图选择器 / `@max-[1100px]` 总数隐藏。
74
+ *
75
+ * ⚠️ @container containment 塌缩约束:三列网格行是 inline-size containment,
76
+ * 若壳被放在「按内容定宽」的水平 flex item 内(行内还有树开关等兄弟件,如
77
+ * testcase list-view),行宽会塌缩到 min-content,三列网格与断点降级全部失真。
78
+ * 消费方必须让壳拿到确定宽度:水平 flex 行内套 `min-w-0 flex-1` 包装层
79
+ * (testcase list-view 先例);flex-col 直排(story / bug list-view)子项默认
80
+ * stretch 拿满宽,无需包装。
81
+ */
82
+ export function ToolbarShell({ left, search, searchFallback, right, below, rowRef }: ToolbarShellProps) {
83
+ return (
84
+ <div className="flex flex-col gap-3">
85
+ <div ref={rowRef} className="grid grid-cols-[1fr_0.5fr_1fr] items-center gap-2 @container">
86
+ {/* 左簇 */}
87
+ <div className="flex items-center gap-2">{left}</div>
88
+
89
+ {/* 中列:w-full 填满列宽(≤15rem 封顶、≥min-w-30),居中放置输入框 */}
90
+ <div className="flex items-center justify-center gap-2">
91
+ {search && (
92
+ <div className="relative w-full min-w-30 max-w-60 @max-[530px]:hidden">{search}</div>
93
+ )}
94
+ {searchFallback}
95
+ </div>
96
+
97
+ {/* 右簇 */}
98
+ <div className="flex shrink-0 items-center gap-2 justify-self-end">{right}</div>
99
+ </div>
100
+ {below}
101
+ </div>
102
+ );
103
+ }
@@ -0,0 +1,115 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-or-later
2
+ // AllBlue - 理想之海
3
+ // Copyright (C) 2026 AllBlue Contributors
4
+ //
5
+ // This program is free software: you can redistribute it and/or modify
6
+ // it under the terms of the GNU Affero General Public License as published by
7
+ // the Free Software Foundation, either version 3 of the License, or
8
+ // (at your option) any later version.
9
+ //
10
+ // This program is distributed in the hope that it will be useful,
11
+ // but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ // GNU Affero General Public License for more details.
14
+ //
15
+ // You should have received a copy of the GNU Affero General Public License
16
+ // along with this program. If not, see <https://www.gnu.org/licenses/>.
17
+
18
+ // useDeferredFlag:真实等待才显示加载指示(follow-up A)。
19
+ // active=true 超过 delayMs 才转 true;期间 active 变 false 立即复位,
20
+ // 快请求(<delayMs 完成)全程不产出 true,消除 loading 闪烁。
21
+ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
22
+ import { renderHook, act } from "@testing-library/react";
23
+ import { useDeferredFlag } from "../use-deferred-flag";
24
+
25
+ beforeEach(() => {
26
+ vi.useFakeTimers();
27
+ });
28
+
29
+ afterEach(() => {
30
+ vi.useRealTimers();
31
+ });
32
+
33
+ describe("useDeferredFlag", () => {
34
+ it("active=false 时恒为 false", () => {
35
+ const { result } = renderHook(() => useDeferredFlag(false, 400));
36
+ expect(result.current).toBe(false);
37
+ act(() => {
38
+ vi.advanceTimersByTime(1000);
39
+ });
40
+ expect(result.current).toBe(false);
41
+ });
42
+
43
+ it("active=true 后 delayMs 内保持 false(快请求零闪烁)", () => {
44
+ const { result } = renderHook(() => useDeferredFlag(true, 400));
45
+ expect(result.current).toBe(false);
46
+ act(() => {
47
+ vi.advanceTimersByTime(399);
48
+ });
49
+ expect(result.current).toBe(false);
50
+ });
51
+
52
+ it("active=true 超过 delayMs 后转为 true(真实等待才显示)", () => {
53
+ const { result } = renderHook(() => useDeferredFlag(true, 400));
54
+ act(() => {
55
+ vi.advanceTimersByTime(400);
56
+ });
57
+ expect(result.current).toBe(true);
58
+ });
59
+
60
+ it("delayMs 未到时 active 变 false 立即复位且定时器不再触发", () => {
61
+ const { result, rerender } = renderHook(({ active }) => useDeferredFlag(active, 400), {
62
+ initialProps: { active: true },
63
+ });
64
+ expect(result.current).toBe(false);
65
+ rerender({ active: false });
66
+ expect(result.current).toBe(false);
67
+ act(() => {
68
+ vi.advanceTimersByTime(1000);
69
+ });
70
+ expect(result.current).toBe(false);
71
+ });
72
+
73
+ it("延迟显示后 active 变 false 立即复位(不等下一帧)", () => {
74
+ const { result, rerender } = renderHook(({ active }) => useDeferredFlag(active, 400), {
75
+ initialProps: { active: true },
76
+ });
77
+ act(() => {
78
+ vi.advanceTimersByTime(400);
79
+ });
80
+ expect(result.current).toBe(true);
81
+ rerender({ active: false });
82
+ expect(result.current).toBe(false);
83
+ });
84
+
85
+ it("active 重新变 true 时重新计时", () => {
86
+ const { result, rerender } = renderHook(({ active }) => useDeferredFlag(active, 400), {
87
+ initialProps: { active: true },
88
+ });
89
+ act(() => {
90
+ vi.advanceTimersByTime(300);
91
+ });
92
+ rerender({ active: false });
93
+ rerender({ active: true });
94
+ act(() => {
95
+ vi.advanceTimersByTime(399);
96
+ });
97
+ expect(result.current).toBe(false);
98
+ act(() => {
99
+ vi.advanceTimersByTime(1);
100
+ });
101
+ expect(result.current).toBe(true);
102
+ });
103
+
104
+ it("默认 delayMs 为 400", () => {
105
+ const { result } = renderHook(() => useDeferredFlag(true));
106
+ act(() => {
107
+ vi.advanceTimersByTime(399);
108
+ });
109
+ expect(result.current).toBe(false);
110
+ act(() => {
111
+ vi.advanceTimersByTime(1);
112
+ });
113
+ expect(result.current).toBe(true);
114
+ });
115
+ });
@@ -0,0 +1,35 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-or-later
2
+ // AllBlue - 理想之海
3
+ // Copyright (C) 2026 AllBlue Contributors
4
+ //
5
+ // This program is free software: you can redistribute it and/or modify
6
+ // it under the terms of the GNU Affero General Public License as published by
7
+ // the Free Software Foundation, either version 3 of the License, or
8
+ // (at your option) any later version.
9
+ //
10
+ // This program is distributed in the hope that it will be useful,
11
+ // but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ // GNU Affero General Public License for more details.
14
+ //
15
+ // You should have received a copy of the GNU Affero General Public License
16
+ // along with this program. If not, see <https://www.gnu.org/licenses/>.
17
+
18
+ // active 为 true 超过 delayMs 才返回 true(真实等待才显示加载指示);
19
+ // active 变 false 立即复位。用于消除快请求下的 loading 闪烁。
20
+ import { useEffect, useState } from "react";
21
+
22
+ export function useDeferredFlag(active: boolean, delayMs = 400): boolean {
23
+ const [deferred, setDeferred] = useState(false);
24
+
25
+ useEffect(() => {
26
+ if (!active) {
27
+ setDeferred(false);
28
+ return;
29
+ }
30
+ const timer = setTimeout(() => setDeferred(true), delayMs);
31
+ return () => clearTimeout(timer);
32
+ }, [active, delayMs]);
33
+
34
+ return deferred;
35
+ }
@@ -0,0 +1,62 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-or-later
2
+ // AllBlue - 理想之海
3
+ // Copyright (C) 2026 AllBlue Contributors
4
+ //
5
+ // This program is free software: you can redistribute it and/or modify
6
+ // it under the terms of the GNU Affero General Public License as published by
7
+ // the Free Software Foundation, either version 3 of the License, or
8
+ // (at your option) any later version.
9
+ //
10
+ // This program is distributed in the hope that it will be useful,
11
+ // but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ // GNU Affero General Public License for more details.
14
+ //
15
+ // You should have received a copy of the GNU Affero General Public License
16
+ // along with this program. If not, see <https://www.gnu.org/licenses/>.
17
+
18
+ // Peek 面板(story / testcase 跨模块共享)侧边面板(side-dock)态的布局槽位解析与应用。
19
+ //
20
+ // 「侧边面板」与其余三种「浮窗」态的本质差异:浮窗态是绝对定位叠加在内容区
21
+ // 之上(不参与布局流),而侧边面板态要把面板搬到右侧内容父容器之外,靠 flex
22
+ // 自然占位把内容区挤窄。因此它必须 portal 到布局级的挂载点
23
+ // (sidebar-03 的 #peek-dock-panel-slot),而不是渲染在自己的
24
+ // `relative` 容器内。
25
+ //
26
+ // 槽位查找是「首帧 → null → 下一帧命中」的两段式:SSR 阶段与首次客户端渲染
27
+ // 时 document 尚未包含布局槽(或 hydration 未完成),若在渲染期直接查 DOM 会
28
+ // 造成 SSR/CSR 结构不一致。故用 useState(null) + useEffect 在提交后解析,
29
+ // 未命中期间退化为非 dock 渲染路径。
30
+
31
+ import { useEffect, useState } from "react";
32
+ import { PEEK_MODE_DOCK, type PeekMode } from "./peek-mode";
33
+
34
+ import { PEEK_DOCK_SLOT_ID, PEEK_SIDE_PANEL_WIDTH_CLASS } from "@/lib/peek-dock";
35
+
36
+ // 常量统一定义在 lib/peek-dock(供布局壳直接引用而不拉入 story serverFn 链),此处再导出给面板消费。
37
+ export { PEEK_DOCK_SLOT_ID, PEEK_SIDE_PANEL_WIDTH_CLASS };
38
+
39
+ /** 当前模式是否走侧边面板(布局占位)路径。 */
40
+ export function isDockMode(mode: PeekMode): boolean {
41
+ return mode === PEEK_MODE_DOCK;
42
+ }
43
+
44
+ /**
45
+ * 解析侧边面板的 portal 挂载点。
46
+ *
47
+ * 返回 null 表示当前不可用(模式非 dock / SSR 首帧 / 布局槽不存在),
48
+ * 调用方应回退到容器内渲染,避免面板整体消失。
49
+ */
50
+ export function usePeekDockSlot(mode: PeekMode): HTMLElement | null {
51
+ const [slot, setSlot] = useState<HTMLElement | null>(null);
52
+
53
+ useEffect(() => {
54
+ if (!isDockMode(mode)) {
55
+ setSlot(null);
56
+ return;
57
+ }
58
+ setSlot(document.getElementById(PEEK_DOCK_SLOT_ID));
59
+ }, [mode]);
60
+
61
+ return slot;
62
+ }
@@ -0,0 +1,34 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-or-later
2
+ // AllBlue - 理想之海
3
+ // Copyright (C) 2026 AllBlue Contributors
4
+ //
5
+ // This program is free software: you can redistribute it and/or modify
6
+ // it under the terms of the GNU Affero General Public License as published by
7
+ // the Free Software Foundation, either version 3 of the License, or
8
+ // (at your option) any later version.
9
+ //
10
+ // This program is distributed in the hope that it will be useful,
11
+ // but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ // GNU Affero General Public License for more details.
14
+ //
15
+ // You should have received a copy of the GNU Affero General Public License
16
+ // along with this program. If not, see <https://www.gnu.org/licenses/>.
17
+
18
+ // Peek 面板的四种展示模式定义(story / testcase 跨模块共享)。
19
+ // label 为惰性求值函数:模块加载时不触发 paraglide 求值,渲染时才取当前语言文案。
20
+
21
+ import { Fullscreen, PanelLeft, PanelLeftDashed, ScanSquare } from "lucide-react";
22
+ import { m } from "@/paraglide/messages.js";
23
+
24
+ export type PeekMode = "side-dock" | "side-peek" | "modal" | "full-screen";
25
+
26
+ /** 侧边面板(dock)态:面板沉入布局槽,与内容区、AI 助手全屏槽三级并排。 */
27
+ export const PEEK_MODE_DOCK: PeekMode = "side-dock";
28
+
29
+ export const PEEK_MODE_OPTIONS: { value: PeekMode; label: () => string; icon: typeof PanelLeft }[] = [
30
+ { value: "side-dock", label: m.story_panel_mode_sideDock, icon: PanelLeft },
31
+ { value: "side-peek", label: m.story_panel_mode_sidePeek, icon: PanelLeftDashed },
32
+ { value: "modal", label: m.story_panel_mode_modal, icon: ScanSquare },
33
+ { value: "full-screen", label: m.story_panel_mode_fullScreen, icon: Fullscreen },
34
+ ];
@@ -18,9 +18,10 @@
18
18
  import { useCallback, useEffect, useRef, useState } from "react"
19
19
  import { Moon, Sun } from "lucide-react"
20
20
  import { flushSync } from "react-dom"
21
- import { useTheme } from "next-themes"
22
21
 
23
22
  import { cn } from "@/lib/utils"
23
+ import { useThemeMode } from "@/providers/theme-mode-provider"
24
+ import { m } from "@/paraglide/messages.js"
24
25
 
25
26
  export type TransitionVariant =
26
27
  | "circle"
@@ -142,6 +143,11 @@ function getThemeTransitionClipPaths(
142
143
  }
143
144
  }
144
145
 
146
+ /**
147
+ * 主题切换器:在明暗之间切换(clip-path 展开动画)。
148
+ * 未手动切换过时主题按系统外观 + 深色时段自动变化(见 ThemeModeProvider);
149
+ * 一旦点击即记为手动选择,此后不再自动切换。
150
+ */
145
151
  export const AnimatedThemeToggler = ({
146
152
  className,
147
153
  duration = 400,
@@ -150,13 +156,13 @@ export const AnimatedThemeToggler = ({
150
156
  ...props
151
157
  }: AnimatedThemeTogglerProps) => {
152
158
  const shape = variant ?? "circle"
153
- const { theme, setTheme } = useTheme()
159
+ const { resolved, toggle } = useThemeMode()
154
160
  const [isDark, setIsDark] = useState(false)
155
161
  const buttonRef = useRef<HTMLButtonElement>(null)
156
162
 
157
163
  useEffect(() => {
158
- setIsDark(theme === "dark")
159
- }, [theme])
164
+ setIsDark(resolved === "dark")
165
+ }, [resolved])
160
166
 
161
167
  const toggleTheme = useCallback(() => {
162
168
  const button = buttonRef.current
@@ -189,7 +195,7 @@ export const AnimatedThemeToggler = ({
189
195
  }
190
196
 
191
197
  const syncNextThemes = () => {
192
- setTheme(newTheme ? "dark" : "light")
198
+ toggle()
193
199
  }
194
200
 
195
201
  if (typeof document.startViewTransition !== "function") {
@@ -254,7 +260,7 @@ export const AnimatedThemeToggler = ({
254
260
  )
255
261
  })
256
262
  }
257
- }, [shape, fromCenter, duration, isDark, setTheme])
263
+ }, [shape, fromCenter, duration, isDark, toggle])
258
264
 
259
265
  return (
260
266
  <button
@@ -265,7 +271,7 @@ export const AnimatedThemeToggler = ({
265
271
  {...props}
266
272
  >
267
273
  {isDark ? <Sun className={cn("size-5", className)} /> : <Moon className={cn("size-5", className)} />}
268
- <span className="sr-only">Toggle theme</span>
274
+ <span className="sr-only">{m.common_command_toggleTheme()}</span>
269
275
  </button>
270
276
  )
271
277
  }
@@ -15,18 +15,13 @@
15
15
  // You should have received a copy of the GNU Affero General Public License
16
16
  // along with this program. If not, see <https://www.gnu.org/licenses/>.
17
17
 
18
- import { useTheme } from "next-themes";
19
18
  import { Moon, Sun } from "lucide-react";
20
19
  import { Button } from "@/components/ui/button";
21
- import { useEffect, useState } from "react";
20
+ import { useThemeMode } from "@/providers/theme-mode-provider";
21
+ import { m } from "@/paraglide/messages.js";
22
22
 
23
23
  export function ThemeToggle() {
24
- const { theme, setTheme } = useTheme();
25
- const [mounted, setMounted] = useState(false);
26
-
27
- useEffect(() => {
28
- setMounted(true);
29
- }, []);
24
+ const { toggle, resolved, mounted } = useThemeMode();
30
25
 
31
26
  if (!mounted) {
32
27
  return (
@@ -36,23 +31,17 @@ export function ThemeToggle() {
36
31
  );
37
32
  }
38
33
 
39
- const toggleTheme = () => {
40
- setTheme(theme === "dark" ? "light" : "dark");
41
- };
34
+ const isDark = resolved === "dark";
42
35
 
43
36
  return (
44
37
  <Button
45
38
  variant="ghost"
46
39
  size="icon"
47
40
  className="h-8 w-8 rounded-full"
48
- onClick={toggleTheme}
41
+ onClick={toggle}
42
+ aria-label={m.common_command_toggleTheme()}
49
43
  >
50
- {theme === "dark" ? (
51
- <Moon className="size-5" />
52
- ) : (
53
- <Sun className="size-5" />
54
- )}
55
- <span className="sr-only">Toggle theme</span>
44
+ {isDark ? <Moon className="size-5" /> : <Sun className="size-5" />}
56
45
  </Button>
57
46
  );
58
47
  }
@@ -0,0 +1,49 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-or-later
2
+ // AllBlue - 理想之海
3
+ // Copyright (C) 2026 AllBlue Contributors
4
+ //
5
+ // This program is free software: you can redistribute it and/or modify
6
+ // it under the terms of the GNU Affero General Public License as published by
7
+ // the Free Software Foundation, either version 3 of the License, or
8
+ // (at your option) any later version.
9
+ //
10
+ // This program is distributed in the hope that it will be useful,
11
+ // but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ // GNU Affero General Public License for more details.
14
+ //
15
+ // You should have received a copy of the GNU Affero General Public License
16
+ // along with this program. If not, see <https://www.gnu.org/licenses/>.
17
+
18
+ import { List, type LucideIcon } from "lucide-react";
19
+ import { LucideIconByName } from "@/components/shared-kit/icons/lucide-icon-picker/lucide-icon-by-name";
20
+ import { VIEW_ICONS } from "@/components/story/views/view-types";
21
+
22
+ /**
23
+ * 视图图标存储的是 lucide kebab-case 名(由 LucideIconPicker 写入,可为任意 lucide 图标)。
24
+ * VIEW_ICONS 只覆盖早期 12 个短名(grid/range/branch/kanban 等并非 lucide 官方名),
25
+ * 故先查旧映射,未命中再按 lucide 官方名解析(精选集同步 + Lab 集异步),仍无效回退 List。
26
+ */
27
+ const LEGACY_VIEW_ICONS: Record<string, LucideIcon> = Object.fromEntries(
28
+ VIEW_ICONS.map((v) => [v.name, v.icon]),
29
+ );
30
+
31
+ interface ViewIconProps {
32
+ /** 图标名(lucide kebab-case 或早期短名) */
33
+ name?: string;
34
+ className?: string;
35
+ size?: number;
36
+ }
37
+
38
+ export function ViewIcon({ name, className, size = 16 }: ViewIconProps) {
39
+ const Legacy = name ? LEGACY_VIEW_ICONS[name] : undefined;
40
+ if (Legacy) return <Legacy className={className} aria-hidden />;
41
+ return (
42
+ <LucideIconByName
43
+ name={name}
44
+ size={size}
45
+ className={className}
46
+ fallback={<List className={className} aria-hidden />}
47
+ />
48
+ );
49
+ }