@taskmark/ui 0.2.6 → 0.3.1

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 (320) hide show
  1. package/README.md +16 -1
  2. package/app/board/page.tsx +3 -272
  3. package/app/globals.css +25 -0
  4. package/app/layout.tsx +15 -5
  5. package/app/page.tsx +14 -14
  6. package/app/setup/actions.ts +4 -4
  7. package/app/setup/page.tsx +9 -4
  8. package/bin/lib/resolve-board.mjs +1 -4
  9. package/bin/taskmark.js +15 -2
  10. package/components/board/app-bar.tsx +3 -0
  11. package/components/board/board-screen.tsx +229 -0
  12. package/components/board/changelog-panel.tsx +26 -0
  13. package/components/board/epic-list.tsx +4 -2
  14. package/components/board/list-view-switcher.tsx +7 -3
  15. package/components/board/markdown-content.tsx +21 -1
  16. package/components/board/mermaid-diagram.tsx +88 -0
  17. package/components/board/metric-stat-card.tsx +4 -4
  18. package/components/board/overall-tree-list.tsx +467 -0
  19. package/components/board/overall-work-items-list.tsx +6 -2
  20. package/components/board/points-heatmap.tsx +183 -0
  21. package/components/board/project-status-metrics-strip.tsx +5 -22
  22. package/components/board/static-board-app.tsx +29 -94
  23. package/components/board/status-badge.tsx +8 -0
  24. package/components/board/story-list.tsx +3 -1
  25. package/components/board/task-list.tsx +5 -1
  26. package/components/board/work-item-detail-body.tsx +123 -8
  27. package/components/board/work-items-list.tsx +2 -0
  28. package/components/theme-provider.tsx +39 -0
  29. package/components/theme-toggle.tsx +27 -0
  30. package/components/ui/sonner.tsx +2 -2
  31. package/dist/prod-next/BUILD_ID +1 -1
  32. package/dist/prod-next/app-path-routes-manifest.json +2 -2
  33. package/dist/prod-next/build-manifest.json +6 -6
  34. package/dist/prod-next/prerender-manifest.json +3 -27
  35. package/dist/prod-next/react-loadable-manifest.json +392 -2
  36. package/dist/prod-next/server/app/_global-error/page.js +2 -2
  37. package/dist/prod-next/server/app/_global-error/page.js.nft.json +1 -1
  38. package/dist/prod-next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  39. package/dist/prod-next/server/app/_global-error.html +1 -1
  40. package/dist/prod-next/server/app/_global-error.rsc +1 -1
  41. package/dist/prod-next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  42. package/dist/prod-next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  43. package/dist/prod-next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  44. package/dist/prod-next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  45. package/dist/prod-next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  46. package/dist/prod-next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  47. package/dist/prod-next/server/app/_not-found/page.js +2 -2
  48. package/dist/prod-next/server/app/_not-found/page.js.nft.json +1 -1
  49. package/dist/prod-next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  50. package/dist/prod-next/server/app/_not-found.html +1 -1
  51. package/dist/prod-next/server/app/_not-found.rsc +19 -17
  52. package/dist/prod-next/server/app/_not-found.segments/_full.segment.rsc +19 -17
  53. package/dist/prod-next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  54. package/dist/prod-next/server/app/_not-found.segments/_index.segment.rsc +8 -6
  55. package/dist/prod-next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  56. package/dist/prod-next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  57. package/dist/prod-next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  58. package/dist/prod-next/server/app/api/taskmark-reload/route.js +1 -1
  59. package/dist/prod-next/server/app/api/taskmark-reload/route.js.nft.json +1 -1
  60. package/dist/prod-next/server/app/board/page.js +2 -50
  61. package/dist/prod-next/server/app/board/page.js.nft.json +1 -1
  62. package/dist/prod-next/server/app/board/page_client-reference-manifest.js +1 -1
  63. package/dist/prod-next/server/app/favicon.ico/route.js +1 -1
  64. package/dist/prod-next/server/app/favicon.ico/route.js.nft.json +1 -1
  65. package/dist/prod-next/server/app/page.js +2 -2
  66. package/dist/prod-next/server/app/page.js.nft.json +1 -1
  67. package/dist/prod-next/server/app/page_client-reference-manifest.js +1 -1
  68. package/dist/prod-next/server/app/setup/page.js +2 -2
  69. package/dist/prod-next/server/app/setup/page.js.nft.json +1 -1
  70. package/dist/prod-next/server/app/setup/page_client-reference-manifest.js +1 -1
  71. package/dist/prod-next/server/app-paths-manifest.json +2 -2
  72. package/dist/prod-next/server/chunks/102.js +90 -0
  73. package/dist/prod-next/server/chunks/11.js +1 -0
  74. package/dist/prod-next/server/chunks/1286.js +1 -0
  75. package/dist/prod-next/server/chunks/1412.js +38 -0
  76. package/dist/prod-next/server/chunks/1605.js +1 -0
  77. package/dist/prod-next/server/chunks/169.js +1 -0
  78. package/dist/prod-next/server/chunks/18.js +86 -0
  79. package/dist/prod-next/server/chunks/2.js +1 -0
  80. package/dist/prod-next/server/chunks/2022.js +1 -0
  81. package/dist/prod-next/server/chunks/2156.js +1 -0
  82. package/dist/prod-next/server/chunks/2157.js +1 -0
  83. package/dist/prod-next/server/chunks/2325.js +82 -0
  84. package/dist/prod-next/server/chunks/2838.js +1 -0
  85. package/dist/prod-next/server/chunks/2897.js +79 -0
  86. package/dist/prod-next/server/chunks/3227.js +1 -0
  87. package/dist/prod-next/server/chunks/3266.js +1 -0
  88. package/dist/prod-next/server/chunks/3307.js +49 -0
  89. package/dist/prod-next/server/chunks/3387.js +19 -0
  90. package/dist/prod-next/server/chunks/3428.js +32 -0
  91. package/dist/prod-next/server/chunks/3479.js +1 -0
  92. package/dist/prod-next/server/chunks/367.js +115 -0
  93. package/dist/prod-next/server/chunks/3698.js +93 -0
  94. package/dist/prod-next/server/chunks/3709.js +148 -0
  95. package/dist/prod-next/server/chunks/41.js +1 -0
  96. package/dist/prod-next/server/chunks/4107.js +62 -0
  97. package/dist/prod-next/server/chunks/4569.js +34 -0
  98. package/dist/prod-next/server/chunks/{741.js → 4741.js} +1 -1
  99. package/dist/prod-next/server/chunks/4755.js +153 -0
  100. package/dist/prod-next/server/chunks/487.js +1 -0
  101. package/dist/prod-next/server/chunks/5002.js +1 -0
  102. package/dist/prod-next/server/chunks/5112.js +1 -0
  103. package/dist/prod-next/server/chunks/5289.js +8 -0
  104. package/dist/prod-next/server/chunks/5318.js +1 -0
  105. package/dist/prod-next/server/chunks/5452.js +23 -0
  106. package/dist/prod-next/server/chunks/5453.js +1 -0
  107. package/dist/prod-next/server/chunks/5749.js +27 -0
  108. package/dist/prod-next/server/chunks/5782.js +36 -0
  109. package/dist/prod-next/server/chunks/6163.js +104 -0
  110. package/dist/prod-next/server/chunks/6169.js +64 -0
  111. package/dist/prod-next/server/chunks/6208.js +172 -0
  112. package/dist/prod-next/server/chunks/6399.js +24 -0
  113. package/dist/prod-next/server/chunks/6496.js +1 -0
  114. package/dist/prod-next/server/chunks/6823.js +215 -0
  115. package/dist/prod-next/server/chunks/6888.js +1 -0
  116. package/dist/prod-next/server/chunks/6980.js +1 -0
  117. package/dist/prod-next/server/chunks/7245.js +77 -0
  118. package/dist/prod-next/server/chunks/7307.js +1 -0
  119. package/dist/prod-next/server/chunks/7372.js +287 -0
  120. package/dist/prod-next/server/chunks/7384.js +226 -0
  121. package/dist/prod-next/server/chunks/7516.js +1 -0
  122. package/dist/prod-next/server/chunks/7531.js +24 -0
  123. package/dist/prod-next/server/chunks/7591.js +1 -0
  124. package/dist/prod-next/server/chunks/7755.js +138 -0
  125. package/dist/prod-next/server/chunks/7916.js +1 -0
  126. package/dist/prod-next/server/chunks/8078.js +94 -0
  127. package/dist/prod-next/server/chunks/8253.js +41 -0
  128. package/dist/prod-next/server/chunks/8635.js +1 -0
  129. package/dist/prod-next/server/chunks/8688.js +1 -0
  130. package/dist/prod-next/server/chunks/8872.js +1 -0
  131. package/dist/prod-next/server/chunks/9006.js +1 -0
  132. package/dist/prod-next/server/chunks/9018.js +1 -0
  133. package/dist/prod-next/server/chunks/9047.js +1 -0
  134. package/dist/prod-next/server/chunks/9108.js +1 -0
  135. package/dist/prod-next/server/chunks/9280.js +256 -0
  136. package/dist/prod-next/server/chunks/9419.js +1 -0
  137. package/dist/prod-next/server/chunks/9430.js +1 -0
  138. package/dist/prod-next/server/chunks/9586.js +1 -0
  139. package/dist/prod-next/server/chunks/9775.js +1 -0
  140. package/dist/prod-next/server/chunks/992.js +1 -0
  141. package/dist/prod-next/server/chunks/9926.js +1 -0
  142. package/dist/prod-next/server/chunks/9984.js +8 -0
  143. package/dist/prod-next/server/middleware-build-manifest.js +1 -1
  144. package/dist/prod-next/server/middleware-react-loadable-manifest.js +1 -1
  145. package/dist/prod-next/server/pages/404.html +1 -1
  146. package/dist/prod-next/server/pages/500.html +1 -1
  147. package/dist/prod-next/server/server-reference-manifest.js +1 -1
  148. package/dist/prod-next/server/server-reference-manifest.json +1 -1
  149. package/dist/prod-next/server/webpack-runtime.js +1 -1
  150. package/dist/prod-next/static/chunks/1213.e5c6e70a79b5f7e6.js +24 -0
  151. package/dist/prod-next/static/chunks/1519.2f596e5f5af9ef57.js +62 -0
  152. package/dist/prod-next/static/chunks/1759-f5b8fb456f8fb420.js +1 -0
  153. package/dist/prod-next/static/chunks/1974.885c9a133b86d8a4.js +32 -0
  154. package/dist/prod-next/static/chunks/2280.6a7f540787704698.js +1 -0
  155. package/dist/prod-next/static/chunks/2521.7f745f50d30076e7.js +77 -0
  156. package/dist/prod-next/static/chunks/2585.4d6aa847c780c666.js +1 -0
  157. package/dist/prod-next/static/chunks/2589.1aad68c09021b1ac.js +1 -0
  158. package/dist/prod-next/static/chunks/2600.45ba17a0f756fc31.js +1 -0
  159. package/dist/prod-next/static/chunks/2619.9aac8983f30c7c8a.js +1 -0
  160. package/dist/prod-next/static/chunks/26d302b2.9f6383e42abdfe16.js +122 -0
  161. package/dist/prod-next/static/chunks/2768.305914f7900745b6.js +1 -0
  162. package/dist/prod-next/static/chunks/2931.c2acdbf72808b646.js +41 -0
  163. package/dist/prod-next/static/chunks/3012-838f69b72a0dc1b3.js +1 -0
  164. package/dist/prod-next/static/chunks/3016.406e568aa95ff867.js +1 -0
  165. package/dist/prod-next/static/chunks/3022.972047558a20553a.js +172 -0
  166. package/dist/prod-next/static/chunks/3064.3a2a1e7cd4fdca5f.js +1 -0
  167. package/dist/prod-next/static/chunks/3174.03fbed7b7d7a8256.js +1 -0
  168. package/dist/prod-next/static/chunks/3189.b048866768087750.js +1 -0
  169. package/dist/prod-next/static/chunks/3217.1a053843c58b70b5.js +24 -0
  170. package/dist/prod-next/static/chunks/3308.30b95d524f9c1daf.js +74 -0
  171. package/dist/prod-next/static/chunks/331.fc5d78e1e91daf43.js +1 -0
  172. package/dist/prod-next/static/chunks/3510.5d4d1c79533e080c.js +1 -0
  173. package/dist/prod-next/static/chunks/364.ce5400a9dd70b9dc.js +1 -0
  174. package/dist/prod-next/static/chunks/3661-1f08d73aaffb011d.js +1 -0
  175. package/dist/prod-next/static/chunks/370.57cfa27da8567918.js +1 -0
  176. package/dist/prod-next/static/chunks/3789.c418b69121761983.js +1 -0
  177. package/dist/prod-next/static/chunks/3794-c66b3d8325973459.js +32 -0
  178. package/dist/prod-next/static/chunks/3831.25ae62d10dccc27a.js +1 -0
  179. package/dist/prod-next/static/chunks/395.b41e9d76613d37b5.js +90 -0
  180. package/dist/prod-next/static/chunks/3a7aa434.93dbd20997cfd24f.js +82 -0
  181. package/dist/prod-next/static/chunks/4020.3cc19c463c49f969.js +23 -0
  182. package/dist/prod-next/static/chunks/4035.0acc428926d5c8dd.js +1 -0
  183. package/dist/prod-next/static/chunks/405.0902e4f6eb7bd9a2.js +215 -0
  184. package/dist/prod-next/static/chunks/4159.49ae537ff687bdc6.js +138 -0
  185. package/dist/prod-next/static/chunks/4208.384b381ca2757643.js +287 -0
  186. package/dist/prod-next/static/chunks/4263.ffa8d9bd8a0faaae.js +1 -0
  187. package/dist/prod-next/static/chunks/4561.d1a3aaca8bae3224.js +34 -0
  188. package/dist/prod-next/static/chunks/4592.d0f37bc216b9d988.js +93 -0
  189. package/dist/prod-next/static/chunks/4799.0dc7aa21bff2fd2a.js +1 -0
  190. package/dist/prod-next/static/chunks/4bd1b696-e356ca5ba0218e27.js +1 -0
  191. package/dist/prod-next/static/chunks/514.b804c51b26f5e126.js +1 -0
  192. package/dist/prod-next/static/chunks/5270.28592864d38e881c.js +1 -0
  193. package/dist/prod-next/static/chunks/52733464.3870f99cc446f9ff.js +1 -0
  194. package/dist/prod-next/static/chunks/5354.b559c717a607dc5c.js +1 -0
  195. package/dist/prod-next/static/chunks/5448.d3972d9fb464b54f.js +38 -0
  196. package/dist/prod-next/static/chunks/587.d52737d7288c11b4.js +1 -0
  197. package/dist/prod-next/static/chunks/5909.9e37f7b495b11995.js +115 -0
  198. package/dist/prod-next/static/chunks/5949.5504b3545fcc3d34.js +104 -0
  199. package/dist/prod-next/static/chunks/6322-4e97920c006f7933.js +1 -0
  200. package/dist/prod-next/static/chunks/6361.893d04ac34fa1b49.js +148 -0
  201. package/dist/prod-next/static/chunks/6774.8cd53427dbf32cac.js +86 -0
  202. package/dist/prod-next/static/chunks/6968.b80277c724dbc96e.js +1 -0
  203. package/dist/prod-next/static/chunks/7113.4b9e7ea870aa300a.js +8 -0
  204. package/dist/prod-next/static/chunks/7236.55a9728d35f5b8a6.js +1 -0
  205. package/dist/prod-next/static/chunks/7390.dde9b5bc2f6e24b8.js +1 -0
  206. package/dist/prod-next/static/chunks/7806.a903780fcfa3a30e.js +1 -0
  207. package/dist/prod-next/static/chunks/7997.be57e92e583fe635.js +1 -0
  208. package/dist/prod-next/static/chunks/8216.64a72d4d35ea7be0.js +1 -0
  209. package/dist/prod-next/static/chunks/830.5d5274d7ad1cb58e.js +1 -0
  210. package/dist/prod-next/static/chunks/8378.fa91de3406f554c9.js +226 -0
  211. package/dist/prod-next/static/chunks/8501.cd06aa1b0c7e1c6a.js +79 -0
  212. package/dist/prod-next/static/chunks/8663.6ec5792fb4952e45.js +27 -0
  213. package/dist/prod-next/static/chunks/872.96937e758ddce860.js +1 -0
  214. package/dist/prod-next/static/chunks/8803.75bde095fe3613f5.js +1 -0
  215. package/dist/prod-next/static/chunks/8863.72f5dbb820a0e4c3.js +1 -0
  216. package/dist/prod-next/static/chunks/90542734.f7a7b2972ef5a749.js +1 -0
  217. package/dist/prod-next/static/chunks/9379.5bc9c9343ec5a16c.js +64 -0
  218. package/dist/prod-next/static/chunks/9389.906fe7aa9cd6a170.js +1 -0
  219. package/dist/prod-next/static/chunks/9472.8818ee52cfa931a4.js +94 -0
  220. package/dist/prod-next/static/chunks/966.d6babbf8119162cc.js +1 -0
  221. package/dist/prod-next/static/chunks/9884.d4ac1a961b3366f1.js +36 -0
  222. package/dist/prod-next/static/chunks/9909.67cf9940b125243b.js +1 -0
  223. package/dist/prod-next/static/chunks/app/_global-error/page-8be5492b3b872a4c.js +1 -0
  224. package/dist/prod-next/static/chunks/app/_not-found/page-799e445a538b0024.js +1 -0
  225. package/dist/prod-next/static/chunks/app/api/taskmark-reload/route-8be5492b3b872a4c.js +1 -0
  226. package/dist/prod-next/static/chunks/app/board/page-5c181f45738daf1c.js +1 -0
  227. package/dist/prod-next/static/chunks/app/layout-21782e6d13a6f275.js +1 -0
  228. package/dist/prod-next/static/chunks/app/page-51bfe4356fe233e3.js +1 -0
  229. package/dist/prod-next/static/chunks/app/setup/page-3ccfba00c10f9b17.js +1 -0
  230. package/dist/prod-next/static/chunks/d3ac728e.7964f816a1ca64e5.js +1 -0
  231. package/dist/prod-next/static/chunks/e413bedd.3a12a8cb02e28fdf.js +153 -0
  232. package/dist/prod-next/static/chunks/ea233666.f00b64a7d99b4950.js +62 -0
  233. package/dist/prod-next/static/chunks/framework-711ef29bc66f648c.js +1 -0
  234. package/dist/prod-next/static/chunks/main-app-dd26d4f9d120646e.js +1 -0
  235. package/dist/prod-next/static/chunks/{main-bb33c46a9c25dee8.js → main-df4bcaed74f274eb.js} +2 -2
  236. package/dist/prod-next/static/chunks/next/dist/client/components/builtin/app-error-8be5492b3b872a4c.js +1 -0
  237. package/dist/prod-next/static/chunks/next/dist/client/components/builtin/forbidden-8be5492b3b872a4c.js +1 -0
  238. package/dist/prod-next/static/chunks/next/dist/client/components/builtin/global-error-45a0cf77e03361ed.js +1 -0
  239. package/dist/prod-next/static/chunks/next/dist/client/components/builtin/not-found-8be5492b3b872a4c.js +1 -0
  240. package/dist/prod-next/static/chunks/next/dist/client/components/builtin/unauthorized-8be5492b3b872a4c.js +1 -0
  241. package/dist/prod-next/static/chunks/webpack-713747aaa9716c4c.js +1 -0
  242. package/dist/prod-next/static/css/cb78d4b0062d9a3f.css +1 -0
  243. package/dist/public/taskmark-snapshot.json +1 -1
  244. package/lib/taskmark/board-index.ts +101 -0
  245. package/lib/taskmark/build-snapshot.ts +28 -7
  246. package/lib/taskmark/derive-parents.test.ts +23 -0
  247. package/lib/taskmark/derive-parents.ts +323 -0
  248. package/lib/taskmark/detail-load.ts +55 -7
  249. package/lib/taskmark/detail-types.ts +10 -2
  250. package/lib/taskmark/dev-reload-token.ts +1 -1
  251. package/lib/taskmark/discover.ts +4 -7
  252. package/lib/taskmark/epic-types.ts +2 -1
  253. package/lib/taskmark/flat-work-item-types.ts +1 -4
  254. package/lib/taskmark/identity.ts +3 -3
  255. package/lib/taskmark/item-types.ts +2 -1
  256. package/lib/taskmark/list-filters.test.ts +23 -0
  257. package/lib/taskmark/list-filters.ts +7 -2
  258. package/lib/taskmark/list-view-mode.test.ts +45 -0
  259. package/lib/taskmark/list-view-mode.ts +20 -9
  260. package/lib/taskmark/load-changelog.test.ts +32 -0
  261. package/lib/taskmark/load-changelog.ts +18 -0
  262. package/lib/taskmark/overall-tree.test.ts +196 -0
  263. package/lib/taskmark/overall-tree.ts +194 -0
  264. package/lib/taskmark/parse-detail.ts +5 -5
  265. package/lib/taskmark/parse-epics.ts +19 -16
  266. package/lib/taskmark/parse-flat-lists.ts +32 -28
  267. package/lib/taskmark/parse-items.ts +47 -9
  268. package/lib/taskmark/parse-stories.ts +18 -15
  269. package/lib/taskmark/points-calendar.test.ts +72 -0
  270. package/lib/taskmark/points-calendar.ts +86 -0
  271. package/lib/taskmark/project-metrics.ts +11 -7
  272. package/lib/taskmark/snapshot-types.ts +2 -0
  273. package/lib/taskmark/story-types.ts +2 -1
  274. package/lib/taskmark/table-sort.ts +4 -3
  275. package/lib/taskmark/timing.ts +29 -18
  276. package/lib/taskmark/validate.ts +1 -1
  277. package/lib/theme-cookie.test.ts +27 -0
  278. package/lib/theme-cookie.ts +43 -0
  279. package/package.json +3 -1
  280. package/public/taskmark-snapshot.json +1 -1
  281. package/scripts/build-static.mjs +61 -3
  282. package/dist/prod-next/server/app/setup.html +0 -1
  283. package/dist/prod-next/server/app/setup.meta +0 -17
  284. package/dist/prod-next/server/app/setup.rsc +0 -22
  285. package/dist/prod-next/server/app/setup.segments/_full.segment.rsc +0 -22
  286. package/dist/prod-next/server/app/setup.segments/_head.segment.rsc +0 -6
  287. package/dist/prod-next/server/app/setup.segments/_index.segment.rsc +0 -8
  288. package/dist/prod-next/server/app/setup.segments/_tree.segment.rsc +0 -5
  289. package/dist/prod-next/server/app/setup.segments/setup/__PAGE__.segment.rsc +0 -6
  290. package/dist/prod-next/server/app/setup.segments/setup.segment.rsc +0 -5
  291. package/dist/prod-next/server/chunks/318.js +0 -1
  292. package/dist/prod-next/server/chunks/490.js +0 -8
  293. package/dist/prod-next/server/chunks/57.js +0 -19
  294. package/dist/prod-next/server/chunks/616.js +0 -1
  295. package/dist/prod-next/server/chunks/708.js +0 -1
  296. package/dist/prod-next/server/chunks/724.js +0 -1
  297. package/dist/prod-next/static/chunks/4bd1b696-deb4a0a1da1923b0.js +0 -1
  298. package/dist/prod-next/static/chunks/51.e9139a9ea6eb36b9.js +0 -1
  299. package/dist/prod-next/static/chunks/613-6f794154d28bb75a.js +0 -1
  300. package/dist/prod-next/static/chunks/669-8103441c67b185da.js +0 -1
  301. package/dist/prod-next/static/chunks/701-df3ee5f1cf837b1a.js +0 -1
  302. package/dist/prod-next/static/chunks/794-25668765560cb197.js +0 -32
  303. package/dist/prod-next/static/chunks/app/_global-error/page-d34451c04262dd7d.js +0 -1
  304. package/dist/prod-next/static/chunks/app/_not-found/page-0b3785af737e7968.js +0 -1
  305. package/dist/prod-next/static/chunks/app/api/taskmark-reload/route-d34451c04262dd7d.js +0 -1
  306. package/dist/prod-next/static/chunks/app/board/page-cd1d9be0c0127225.js +0 -1
  307. package/dist/prod-next/static/chunks/app/layout-856e8a282e69e7d0.js +0 -1
  308. package/dist/prod-next/static/chunks/app/page-d34451c04262dd7d.js +0 -1
  309. package/dist/prod-next/static/chunks/app/setup/page-c3003359e8becc84.js +0 -1
  310. package/dist/prod-next/static/chunks/framework-b29f9083d3cda3b2.js +0 -1
  311. package/dist/prod-next/static/chunks/main-app-bfb36455d24b3e5a.js +0 -1
  312. package/dist/prod-next/static/chunks/next/dist/client/components/builtin/app-error-d34451c04262dd7d.js +0 -1
  313. package/dist/prod-next/static/chunks/next/dist/client/components/builtin/forbidden-d34451c04262dd7d.js +0 -1
  314. package/dist/prod-next/static/chunks/next/dist/client/components/builtin/global-error-dc53ab29e0491fe4.js +0 -1
  315. package/dist/prod-next/static/chunks/next/dist/client/components/builtin/not-found-d34451c04262dd7d.js +0 -1
  316. package/dist/prod-next/static/chunks/next/dist/client/components/builtin/unauthorized-d34451c04262dd7d.js +0 -1
  317. package/dist/prod-next/static/chunks/webpack-bfe8992962004e2b.js +0 -1
  318. package/dist/prod-next/static/css/2e6ec4c80894e3c0.css +0 -1
  319. /package/dist/prod-next/static/{sAWr5ATVuqk6Wqs18kAWs → EI1zQaa_kQ7DqUSE4o3Qo}/_buildManifest.js +0 -0
  320. /package/dist/prod-next/static/{sAWr5ATVuqk6Wqs18kAWs → EI1zQaa_kQ7DqUSE4o3Qo}/_ssgManifest.js +0 -0
@@ -0,0 +1,229 @@
1
+ import { Suspense } from "react"
2
+ import { redirect } from "next/navigation"
3
+
4
+ import { AppBar } from "@/components/board/app-bar"
5
+ import { ChangelogPanel } from "@/components/board/changelog-panel"
6
+ import { ListViewSwitcher } from "@/components/board/list-view-switcher"
7
+ import { OverallTreeList } from "@/components/board/overall-tree-list"
8
+ import { PointsHeatmap } from "@/components/board/points-heatmap"
9
+ import { ProjectStatusMetricsStrip } from "@/components/board/project-status-metrics-strip"
10
+ import { StaticBoardApp } from "@/components/board/static-board-app"
11
+ import { WorkItemsList } from "@/components/board/work-items-list"
12
+ import { WorkItemSheetProvider } from "@/components/board/work-item-sheet"
13
+ import { resolveActiveProject } from "@/lib/taskmark/active-project"
14
+ import { buildBoardIndex } from "@/lib/taskmark/board-index"
15
+ import {
16
+ getActiveProjectCookie,
17
+ getHideCompletedCookies,
18
+ getMasterFoldersCookie,
19
+ } from "@/lib/taskmark/cookies"
20
+ import {
21
+ LIST_VIEW_LABELS,
22
+ parseListViewMode,
23
+ type ListViewMode,
24
+ } from "@/lib/taskmark/list-view-mode"
25
+ import { DEV_RELOAD_TOKEN } from "@/lib/taskmark/dev-reload-token"
26
+ import { loadSnapshotFromPublic } from "@/lib/taskmark/load-snapshot-server"
27
+ import { parseEpicsForProject } from "@/lib/taskmark/parse-epics"
28
+ import {
29
+ parseWorkItemsForEpic,
30
+ parseWorkItemsViewForProject,
31
+ } from "@/lib/taskmark/parse-flat-lists"
32
+ import { loadBoardChangelogMarkdown } from "@/lib/taskmark/load-changelog"
33
+ import { parseItemsForStory } from "@/lib/taskmark/parse-items"
34
+ import { storyKey } from "@/lib/taskmark/snapshot-types"
35
+ import {
36
+ collectCompletedLeafPointSamples,
37
+ collectMetricLeaves,
38
+ computeProjectStatusMetrics,
39
+ } from "@/lib/taskmark/project-metrics"
40
+ import { isStaticRuntime } from "@/lib/taskmark/static-mode"
41
+ import { loadWorkspace } from "@/lib/taskmark/workspace"
42
+
43
+ // Keep this import so `taskmark dev` can touch the token module and refresh RSC.
44
+ void DEV_RELOAD_TOKEN
45
+
46
+ type BoardScreenProps = {
47
+ searchParams: Promise<{
48
+ view?: string | string[]
49
+ epic?: string | string[]
50
+ story?: string | string[]
51
+ item?: string | string[]
52
+ }>
53
+ }
54
+
55
+
56
+ function paramValue(value: string | string[] | undefined): string | null {
57
+ if (typeof value === "string" && value.trim()) return value.trim()
58
+ return null
59
+ }
60
+
61
+ function headingForView(view: ListViewMode): string {
62
+ if (view === "overall") return "Overall"
63
+ return LIST_VIEW_LABELS[view]
64
+ }
65
+
66
+ export async function BoardScreen({ searchParams }: BoardScreenProps) {
67
+ if (isStaticRuntime()) {
68
+ const snapshot = loadSnapshotFromPublic()
69
+ return (
70
+ <Suspense fallback={<div className="p-8 text-sm text-muted-foreground">Loading board…</div>}>
71
+ <StaticBoardApp snapshot={snapshot} />
72
+ </Suspense>
73
+ )
74
+ }
75
+
76
+ const masters = await getMasterFoldersCookie()
77
+ const workspace = loadWorkspace(masters)
78
+ if (workspace.projects.length === 0) {
79
+ redirect("/setup")
80
+ }
81
+
82
+ const savedActiveId = await getActiveProjectCookie()
83
+ const hideCompletedPrefs = await getHideCompletedCookies()
84
+ const activeProject = resolveActiveProject(
85
+ workspace.projects,
86
+ // Autoconfig: prefer the bound board; ignore stale active-project cookies.
87
+ workspace.autoconfig ? null : savedActiveId
88
+ )
89
+ if (!activeProject) {
90
+ redirect("/setup")
91
+ }
92
+
93
+ const params = await searchParams
94
+ const boardIndex = buildBoardIndex(activeProject.boardPath)
95
+ const changelogMarkdown = loadBoardChangelogMarkdown(activeProject.boardPath)
96
+ const hasChangelog = changelogMarkdown != null
97
+ const activeView = parseListViewMode(params.view, { hasChangelog })
98
+ const selectedEpicId =
99
+ activeView === "overall" ? paramValue(params.epic) : null
100
+ const selectedStoryId =
101
+ activeView === "overall" && selectedEpicId
102
+ ? paramValue(params.story)
103
+ : null
104
+ const list = parseEpicsForProject(activeProject, boardIndex)
105
+ const epicCount = list.epics.length
106
+ const errorCount = list.errors.length
107
+
108
+ const selectedEpic = selectedEpicId
109
+ ? list.epics.find((e) => e.id === selectedEpicId) ?? null
110
+ : null
111
+
112
+ const workItemsByEpic: Record<
113
+ string,
114
+ ReturnType<typeof parseWorkItemsForEpic>
115
+ > = {}
116
+ const itemsByStory: Record<string, ReturnType<typeof parseItemsForStory>> = {}
117
+ if (activeView === "overall") {
118
+ for (const epic of list.epics) {
119
+ const epicItems = parseWorkItemsForEpic(
120
+ activeProject,
121
+ epic.id,
122
+ epic.title,
123
+ boardIndex
124
+ )
125
+ workItemsByEpic[epic.id] = epicItems
126
+ for (const row of epicItems.rows) {
127
+ if (row.kind !== "story") continue
128
+ itemsByStory[storyKey(epic.id, row.id)] = parseItemsForStory(
129
+ activeProject,
130
+ epic.id,
131
+ row.id,
132
+ boardIndex
133
+ )
134
+ }
135
+ }
136
+ }
137
+
138
+ const workItemsList =
139
+ activeView === "workitems"
140
+ ? parseWorkItemsViewForProject(activeProject, boardIndex)
141
+ : null
142
+
143
+ const metricLeaves = collectMetricLeaves(activeProject, boardIndex)
144
+ /** Match Current Speed exactly: completed task/bug leaf points only. */
145
+ const countableCompletions =
146
+ collectCompletedLeafPointSamples(metricLeaves)
147
+ const statusMetrics = computeProjectStatusMetrics(
148
+ activeProject,
149
+ boardIndex,
150
+ metricLeaves
151
+ )
152
+
153
+ return (
154
+ <WorkItemSheetProvider>
155
+ <div className="tm-surface min-h-svh">
156
+ <AppBar
157
+ projects={workspace.projects}
158
+ activeProjectId={activeProject.id}
159
+ autoconfig={workspace.autoconfig}
160
+ />
161
+
162
+ <div className="mx-auto flex w-full max-w-5xl flex-col gap-6 px-4 py-8">
163
+ <div className="flex flex-col gap-4 sm:flex-row sm:items-start sm:justify-between">
164
+ <div>
165
+ <h1 className="font-head text-3xl tracking-tight">
166
+ {headingForView(activeView)}
167
+ </h1>
168
+ <p className="mt-1 text-sm text-muted-foreground">
169
+ {activeProject.name}
170
+ {activeView === "overall"
171
+ ? ` · ${epicCount} epic${epicCount === 1 ? "" : "s"}`
172
+ : ""}
173
+ {activeView === "overall" && errorCount > 0
174
+ ? ` · ${errorCount} parse issue${errorCount === 1 ? "" : "s"}`
175
+ : ""}
176
+ {activeView === "workitems" && workItemsList
177
+ ? ` · ${workItemsList.rows.length} item${workItemsList.rows.length === 1 ? "" : "s"}`
178
+ : ""}
179
+ {activeView === "overall" && selectedEpic
180
+ ? ` · expanded ${selectedEpic.id}`
181
+ : activeView === "overall" && selectedEpicId
182
+ ? ` · epic ${selectedEpicId} not in list`
183
+ : ""}
184
+ {activeView === "overall" && selectedStoryId
185
+ ? ` · story ${selectedStoryId}`
186
+ : ""}
187
+ </p>
188
+ </div>
189
+ <ListViewSwitcher
190
+ activeView={activeView}
191
+ selectedEpicId={selectedEpicId}
192
+ selectedStoryId={selectedStoryId}
193
+ hasChangelog={hasChangelog}
194
+ />
195
+ </div>
196
+
197
+ <ProjectStatusMetricsStrip metrics={statusMetrics} />
198
+
199
+ {activeView === "overall" ? (
200
+ <>
201
+ <PointsHeatmap samples={countableCompletions} />
202
+ <OverallTreeList
203
+ list={list}
204
+ workItemsByEpic={workItemsByEpic}
205
+ itemsByStory={itemsByStory}
206
+ selectedEpicId={selectedEpicId}
207
+ selectedStoryId={selectedStoryId}
208
+ countableCompletions={countableCompletions}
209
+ initialHideCompleted={hideCompletedPrefs.epics}
210
+ />
211
+ </>
212
+ ) : null}
213
+
214
+ {activeView === "workitems" && workItemsList ? (
215
+ <WorkItemsList
216
+ list={workItemsList}
217
+ countableCompletions={countableCompletions}
218
+ initialHideCompleted={hideCompletedPrefs.workItems}
219
+ />
220
+ ) : null}
221
+
222
+ {activeView === "changelog" && changelogMarkdown ? (
223
+ <ChangelogPanel markdown={changelogMarkdown} />
224
+ ) : null}
225
+ </div>
226
+ </div>
227
+ </WorkItemSheetProvider>
228
+ )
229
+ }
@@ -0,0 +1,26 @@
1
+ "use client"
2
+
3
+ import { MarkdownContent } from "@/components/board/markdown-content"
4
+ import {
5
+ Card,
6
+ CardContent,
7
+ CardDescription,
8
+ CardHeader,
9
+ CardTitle,
10
+ } from "@/components/ui/card"
11
+
12
+ export function ChangelogPanel({ markdown }: { markdown: string }) {
13
+ return (
14
+ <Card>
15
+ <CardHeader>
16
+ <CardTitle className="font-head text-xl">Changelog</CardTitle>
17
+ <CardDescription>
18
+ Board-root CHANGELOG.md (Keep a Changelog)
19
+ </CardDescription>
20
+ </CardHeader>
21
+ <CardContent>
22
+ <MarkdownContent text={markdown} />
23
+ </CardContent>
24
+ </Card>
25
+ )
26
+ }
@@ -26,6 +26,7 @@ import { ChildProgressBar } from "@/components/board/child-progress-bar"
26
26
  import { ListFiltersBar } from "@/components/board/list-filters-bar"
27
27
  import { ListPagination } from "@/components/board/list-pagination"
28
28
  import { SortableTableHead } from "@/components/board/sortable-table-head"
29
+ import { statusRowClass } from "@/components/board/status-badge"
29
30
  import { TimeframeFilter } from "@/components/board/timeframe-filter"
30
31
  import { ViewWorkItemButton } from "@/components/board/work-item-sheet"
31
32
  import { AttributionAvatarGroup } from "@/components/board/attribution-avatars"
@@ -246,6 +247,7 @@ function ProjectEpicCard({
246
247
  key={`${project.id}:${epic.id}:${epic.filePath}`}
247
248
  data-state={selected ? "selected" : undefined}
248
249
  className={cn(
250
+ statusRowClass(epic.status),
249
251
  selected && "bg-muted/60",
250
252
  "hover:bg-muted/40"
251
253
  )}
@@ -263,7 +265,7 @@ function ProjectEpicCard({
263
265
  <TableCell className="font-mono text-xs">
264
266
  <IdCreatedTooltip id={epic.id} created={epic.created}>
265
267
  <Link
266
- href={`/board?epic=${encodeURIComponent(epic.id)}`}
268
+ href={`/?epic=${encodeURIComponent(epic.id)}`}
267
269
  className="underline-offset-2 hover:underline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring"
268
270
  aria-current={selected ? "true" : undefined}
269
271
  >
@@ -273,7 +275,7 @@ function ProjectEpicCard({
273
275
  </TableCell>
274
276
  <TableCell className="max-w-[18rem] whitespace-normal font-medium">
275
277
  <Link
276
- href={`/board?epic=${encodeURIComponent(epic.id)}`}
278
+ href={`/?epic=${encodeURIComponent(epic.id)}`}
277
279
  className="underline-offset-2 hover:underline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring"
278
280
  >
279
281
  {epic.title}
@@ -6,8 +6,8 @@ import { useRouter, useSearchParams } from "next/navigation"
6
6
  import { Tabs, TabsList, TabsTrigger } from "@/components/ui/tabs"
7
7
  import {
8
8
  LIST_VIEW_LABELS,
9
- LIST_VIEW_MODES,
10
9
  boardHref,
10
+ listViewModes,
11
11
  type ListViewMode,
12
12
  } from "@/lib/taskmark/list-view-mode"
13
13
 
@@ -15,16 +15,19 @@ type ListViewSwitcherProps = {
15
15
  activeView: ListViewMode
16
16
  selectedEpicId?: string | null
17
17
  selectedStoryId?: string | null
18
+ hasChangelog?: boolean
18
19
  }
19
20
 
20
21
  function ListViewSwitcherInner({
21
22
  activeView,
22
23
  selectedEpicId = null,
23
24
  selectedStoryId = null,
25
+ hasChangelog = false,
24
26
  }: ListViewSwitcherProps) {
25
27
  const router = useRouter()
26
28
  const searchParams = useSearchParams()
27
29
  const itemId = searchParams.get("item")
30
+ const modes = listViewModes(hasChangelog)
28
31
 
29
32
  return (
30
33
  <Tabs
@@ -43,7 +46,7 @@ function ListViewSwitcherInner({
43
46
  }}
44
47
  >
45
48
  <TabsList aria-label="Board list view">
46
- {LIST_VIEW_MODES.map((mode) => (
49
+ {modes.map((mode) => (
47
50
  <TabsTrigger key={mode} value={mode}>
48
51
  {LIST_VIEW_LABELS[mode]}
49
52
  </TabsTrigger>
@@ -54,12 +57,13 @@ function ListViewSwitcherInner({
54
57
  }
55
58
 
56
59
  export function ListViewSwitcher(props: ListViewSwitcherProps) {
60
+ const modes = listViewModes(props.hasChangelog ?? false)
57
61
  return (
58
62
  <React.Suspense
59
63
  fallback={
60
64
  <Tabs value={props.activeView}>
61
65
  <TabsList aria-label="Board list view">
62
- {LIST_VIEW_MODES.map((mode) => (
66
+ {modes.map((mode) => (
63
67
  <TabsTrigger key={mode} value={mode} disabled>
64
68
  {LIST_VIEW_LABELS[mode]}
65
69
  </TabsTrigger>
@@ -1,10 +1,22 @@
1
1
  "use client"
2
2
 
3
+ import { isValidElement, type ReactNode } from "react"
3
4
  import ReactMarkdown from "react-markdown"
4
5
  import remarkGfm from "remark-gfm"
5
6
 
7
+ import { MermaidDiagram } from "@/components/board/mermaid-diagram"
6
8
  import { cn } from "@/lib/utils"
7
9
 
10
+ function mermaidSourceFromPreChildren(children: ReactNode): string | null {
11
+ const child = Array.isArray(children) ? children[0] : children
12
+ if (!isValidElement<{ className?: string; children?: ReactNode }>(child)) {
13
+ return null
14
+ }
15
+ const className = child.props.className ?? ""
16
+ if (!className.includes("language-mermaid")) return null
17
+ return String(child.props.children ?? "").replace(/\n$/, "")
18
+ }
19
+
8
20
  type MarkdownContentProps = {
9
21
  text: string
10
22
  className?: string
@@ -71,7 +83,15 @@ export function MarkdownContent({
71
83
  ol: ({ children }) => <span>{children}</span>,
72
84
  li: ({ children }) => <span>{children} </span>,
73
85
  }
74
- : undefined
86
+ : {
87
+ pre({ children }) {
88
+ const mermaidSource = mermaidSourceFromPreChildren(children)
89
+ if (mermaidSource !== null) {
90
+ return <MermaidDiagram chart={mermaidSource} />
91
+ }
92
+ return <pre>{children}</pre>
93
+ },
94
+ }
75
95
  }
76
96
  >
77
97
  {trimmed}
@@ -0,0 +1,88 @@
1
+ "use client"
2
+
3
+ import { useEffect, useId, useState } from "react"
4
+
5
+ function pageIsDark(): boolean {
6
+ if (typeof document === "undefined") return false
7
+ return Boolean(
8
+ document.documentElement.classList.contains("dark") ||
9
+ document.body.classList.contains("dark")
10
+ )
11
+ }
12
+
13
+ export function MermaidDiagram({ chart }: { chart: string }) {
14
+ const reactId = useId().replace(/:/g, "")
15
+ const [dark, setDark] = useState(false)
16
+ const [svg, setSvg] = useState<string | null>(null)
17
+ const [error, setError] = useState<string | null>(null)
18
+
19
+ useEffect(() => {
20
+ const syncDark = () => setDark(pageIsDark())
21
+ syncDark()
22
+ const observer = new MutationObserver(syncDark)
23
+ observer.observe(document.documentElement, {
24
+ attributes: true,
25
+ attributeFilter: ["class"],
26
+ })
27
+ observer.observe(document.body, {
28
+ attributes: true,
29
+ attributeFilter: ["class"],
30
+ })
31
+ return () => observer.disconnect()
32
+ }, [])
33
+
34
+ useEffect(() => {
35
+ let cancelled = false
36
+
37
+ async function renderChart() {
38
+ try {
39
+ const mermaid = (await import("mermaid")).default
40
+ mermaid.initialize({
41
+ startOnLoad: false,
42
+ securityLevel: "strict",
43
+ theme: dark ? "dark" : "neutral",
44
+ })
45
+ const { svg: rendered } = await mermaid.render(
46
+ `tm-mermaid-${reactId}-${dark ? "d" : "l"}`,
47
+ chart
48
+ )
49
+ if (!cancelled) {
50
+ setSvg(rendered)
51
+ setError(null)
52
+ }
53
+ } catch (cause) {
54
+ if (!cancelled) {
55
+ setSvg(null)
56
+ setError(
57
+ cause instanceof Error ? cause.message : "Could not render diagram"
58
+ )
59
+ }
60
+ }
61
+ }
62
+
63
+ void renderChart()
64
+ return () => {
65
+ cancelled = true
66
+ }
67
+ }, [chart, reactId, dark])
68
+
69
+ if (error) {
70
+ return (
71
+ <div className="my-2 rounded border-2 border-border bg-muted p-3">
72
+ <p className="text-xs text-destructive">{error}</p>
73
+ <pre className="mt-2 overflow-x-auto font-mono text-xs">{chart}</pre>
74
+ </div>
75
+ )
76
+ }
77
+
78
+ if (!svg) {
79
+ return <p className="text-sm text-muted-foreground">Rendering diagram…</p>
80
+ }
81
+
82
+ return (
83
+ <div
84
+ className="tm-mermaid my-2 max-w-full overflow-x-auto"
85
+ dangerouslySetInnerHTML={{ __html: svg }}
86
+ />
87
+ )
88
+ }
@@ -26,15 +26,15 @@ export function MetricStatCard({
26
26
  return (
27
27
  <div
28
28
  className={cn(
29
- "flex min-h-[7.5rem] flex-col justify-between gap-3 border-2 border-black bg-white p-4 shadow-none",
29
+ "flex min-h-[7.5rem] flex-col justify-between gap-3 border-2 border-black bg-card p-4 shadow-none",
30
30
  className
31
31
  )}
32
32
  >
33
33
  <div className="flex items-start justify-between gap-3">
34
- <p className="text-sm font-medium text-neutral-800">{title}</p>
34
+ <p className="text-sm font-medium text-card-foreground">{title}</p>
35
35
  <div
36
36
  className={cn(
37
- "flex size-9 shrink-0 items-center justify-center border-2 border-black text-black shadow-[3px_3px_0_0_#000]",
37
+ "flex size-9 shrink-0 items-center justify-center border-2 border-black text-black shadow-[3px_3px_0_0_var(--shadow-color)]",
38
38
  accentClassName
39
39
  )}
40
40
  aria-hidden
@@ -43,7 +43,7 @@ export function MetricStatCard({
43
43
  </div>
44
44
  </div>
45
45
  <div className="flex flex-col gap-1">
46
- <p className="font-head text-3xl font-bold leading-none tracking-tight text-black tabular-nums sm:text-4xl">
46
+ <p className="font-head text-3xl font-bold leading-none tracking-tight text-card-foreground tabular-nums sm:text-4xl">
47
47
  {value}
48
48
  </p>
49
49
  {subtitle ? (