kennel 0.2.2 → 0.2.5

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 (237) hide show
  1. package/README.md +23 -13
  2. package/dist/cli/dispatch.js +16 -3
  3. package/dist/cli/src/cli/dispatch.js +16 -3
  4. package/dist/cli/src/cli/usage.js +1 -1
  5. package/dist/cli/src/core/command.js +1 -0
  6. package/dist/cli/src/core/init.js +5 -5
  7. package/dist/cli/src/plugins/external.d.ts +29 -3
  8. package/dist/cli/src/plugins/external.js +78 -24
  9. package/dist/cli/src/site/server-plugins.d.ts +2 -7
  10. package/dist/cli/src/site/viewer.js +1 -0
  11. package/dist/cli/usage.js +1 -1
  12. package/dist/core/command.js +1 -0
  13. package/dist/core/init.js +5 -5
  14. package/dist/core/runtime.js +357 -3207
  15. package/dist/package/preview.js +1232 -5113
  16. package/dist/plugins/external.d.ts +29 -3
  17. package/dist/plugins/external.js +78 -24
  18. package/dist/site/server-plugins.d.ts +2 -7
  19. package/dist/site/server-plugins.js +552 -10447
  20. package/dist/site/viewer.js +1 -0
  21. package/kernel/apps/web/package.json +1 -5
  22. package/kernel/apps/web/scripts/dev.mjs +53 -0
  23. package/kernel/apps/web/src/app.css +0 -3
  24. package/kernel/apps/web/src/main.tsx +0 -1
  25. package/kernel/apps/web/src/plugins.ts +0 -30
  26. package/kernel/apps/web/tsconfig.json +1 -2
  27. package/kernel/apps/web/vite.config.ts +31 -13
  28. package/kernel/packages/api/package.json +0 -4
  29. package/kernel/packages/api/src/server/folder-metadata-plugin.ts +13 -38
  30. package/kernel/packages/api/src/server/index.ts +0 -1
  31. package/kernel/packages/api/src/server/plugins.ts +49 -16
  32. package/kernel/packages/api/test/core.test.ts +13 -25
  33. package/kernel/packages/markdown/README.md +1 -1
  34. package/package.json +1 -1
  35. package/web/assets/{abnfDiagram-VRR7QNED-Bgfb1nEB.js → abnfDiagram-VRR7QNED-xd_g1uK3.js} +1 -1
  36. package/web/assets/app-CX20nNIa.js +2 -0
  37. package/web/assets/{app-options-D-RJiQ-X.js → app-options-CkPJE5ep.js} +1 -1
  38. package/web/assets/{app-view-header-BLvLq02T.js → app-view-header-CNk5KnA-.js} +1 -1
  39. package/web/assets/{arc-Dk_KI36B.js → arc-B0u5yBJA.js} +1 -1
  40. package/web/assets/{architectureDiagram-ZJ3FMSHR-NR_KhRCf.js → architectureDiagram-ZJ3FMSHR-DfxOAo8P.js} +1 -1
  41. package/web/assets/{ask-tray-TzeTcO6-.js → ask-tray-SscJecDY.js} +1 -1
  42. package/web/assets/{blockDiagram-677ZJIJ3-CkLkwx9C.js → blockDiagram-677ZJIJ3-Ci3Usxh6.js} +1 -1
  43. package/web/assets/{c4Diagram-LMCZKHZV-CFCUH8e_.js → c4Diagram-LMCZKHZV-BqgwIVgh.js} +1 -1
  44. package/web/assets/channel-X7WHyxxT.js +1 -0
  45. package/web/assets/{chunk-2Q5K7J3B-B_BPLWsW.js → chunk-2Q5K7J3B-CfX69l2U.js} +1 -1
  46. package/web/assets/{chunk-32BRIVSS-B1VB1hOy.js → chunk-32BRIVSS-CuFlzZkl.js} +1 -1
  47. package/web/assets/{chunk-5VM5RSS4-KFcYr8Co.js → chunk-5VM5RSS4-DidCMlJa.js} +1 -1
  48. package/web/assets/{chunk-EX3LRPZG-CpBX3kuK.js → chunk-EX3LRPZG-B5CDm1dS.js} +1 -1
  49. package/web/assets/{chunk-JWPE2WC7-BPSl40wG.js → chunk-JWPE2WC7-D5fGV_sH.js} +1 -1
  50. package/web/assets/{chunk-MOJQB5TN-D2RcYmoU.js → chunk-MOJQB5TN-ayhH5Q-H.js} +1 -1
  51. package/web/assets/{chunk-RYQCIY6F-m7Gyn-t3.js → chunk-RYQCIY6F-C4BfOOZn.js} +1 -1
  52. package/web/assets/{chunk-V7JOEXUC-TDvdopxS.js → chunk-V7JOEXUC-DpUEIM9V.js} +1 -1
  53. package/web/assets/{chunk-VR4S4FIN-DZTsG51a.js → chunk-VR4S4FIN-DoQuFFRh.js} +1 -1
  54. package/web/assets/{chunk-XXDRQBXY-Dp0--RE2.js → chunk-XXDRQBXY-CI9eiLwn.js} +1 -1
  55. package/web/assets/classDiagram-OUVF2IWQ-BjsLQ3dz.js +1 -0
  56. package/web/assets/classDiagram-v2-EOCWNBFH-BjsLQ3dz.js +1 -0
  57. package/web/assets/client-7OWw5kW2.js +6 -0
  58. package/web/assets/client-DYj_td4Q.js +17 -0
  59. package/web/assets/{client-j2kQmxsO.js → client-Dk-NBvJR.js} +4 -4
  60. package/web/assets/command-zkzH4hVz.js +38 -0
  61. package/web/assets/{copy-context-C0Uqsp-3.js → copy-context-D5oiWrYC.js} +1 -1
  62. package/web/assets/{cose-bilkent-JH36ORCC-CPu3PI8h.js → cose-bilkent-JH36ORCC-BHRk1mO3.js} +1 -1
  63. package/web/assets/{cynefin-VYW2F7L2-DWxftYAm.js → cynefin-VYW2F7L2-C1B09TRE.js} +1 -1
  64. package/web/assets/{cynefinDiagram-TSTJHNR4-DsmN2V-p.js → cynefinDiagram-TSTJHNR4-B27qXQbv.js} +1 -1
  65. package/web/assets/{dagre-VKFMJZFB-COEbApyY.js → dagre-VKFMJZFB-B1qEi32g.js} +1 -1
  66. package/web/assets/{diagram-FQU43EPY-0O9WGWKB.js → diagram-FQU43EPY-BMkkgADD.js} +1 -1
  67. package/web/assets/{diagram-G47NLZAW-CutEdMVh.js → diagram-G47NLZAW-Cb8_g1A5.js} +1 -1
  68. package/web/assets/{diagram-NH7WQ7WH-C9KZc3B2.js → diagram-NH7WQ7WH-B51wuc5m.js} +1 -1
  69. package/web/assets/{diagram-OA4YK3LP-D8kkPXbY.js → diagram-OA4YK3LP-xnsecbbI.js} +1 -1
  70. package/web/assets/{diagram-WEI45ONY-_YqiTaGP.js → diagram-WEI45ONY-DSZdyaAV.js} +1 -1
  71. package/web/assets/{document-Dgt5eZFj.js → document-Dc2dftTW.js} +3 -3
  72. package/web/assets/{ebnfDiagram-CCIWWBDH-JO-zQh6g.js → ebnfDiagram-CCIWWBDH-aTHmcUGy.js} +1 -1
  73. package/web/assets/{entities-C3wz7FCx.js → entities-CCUtpskY.js} +1 -1
  74. package/web/assets/{erDiagram-Q63AITRT-9UjQwJ4P.js → erDiagram-Q63AITRT-CUUPBcvo.js} +1 -1
  75. package/web/assets/{file-viewer-DZJ8nYnl.js → file-viewer-DJ3rsmef.js} +1 -1
  76. package/web/assets/{flowDiagram-23GEKE2U-Ca08tnYM.js → flowDiagram-23GEKE2U-aTQXx2Mh.js} +1 -1
  77. package/web/assets/{folder-image-BfGgxo7i.js → folder-image-Bnv43tzP.js} +1 -1
  78. package/web/assets/{folder-landing-qUKBCnG-.js → folder-landing-DCnzYXXY.js} +1 -1
  79. package/web/assets/{folder-list-BfFjv7rR.js → folder-list-DvVkVjiR.js} +1 -1
  80. package/web/assets/{folder-metadata-DCw8xzHk.js → folder-metadata-C9hMMzIH.js} +1 -1
  81. package/web/assets/{folder-mobile-bar-Ubz4babf.js → folder-mobile-bar-VoTL1GS0.js} +1 -1
  82. package/web/assets/folder-plugin-view-Cvd804ZU.js +6 -0
  83. package/web/assets/{ganttDiagram-NO4QXBWP-KnHzX5W3.js → ganttDiagram-NO4QXBWP-DiwdUp7u.js} +1 -1
  84. package/web/assets/{gitGraphDiagram-IHSO6WYX-Cm8woNtK.js → gitGraphDiagram-IHSO6WYX-BL2gG_IS.js} +1 -1
  85. package/web/assets/{index-CNyy98F8.js → index-CUTtMSyJ.js} +2 -2
  86. package/web/assets/index-CegvVQ1C.js +1 -0
  87. package/web/assets/index-Dwhf8F_U.css +1 -0
  88. package/web/assets/{infoDiagram-FWYZ7A6U-yyqmUtIb.js → infoDiagram-FWYZ7A6U-B3n0zZpt.js} +1 -1
  89. package/web/assets/{ishikawaDiagram-FXEZZL3T-BfvR_Zy4.js → ishikawaDiagram-FXEZZL3T-D7YytbEv.js} +1 -1
  90. package/web/assets/{journeyDiagram-5HDEW3XC-BKuw06HM.js → journeyDiagram-5HDEW3XC-BYwqEl3C.js} +1 -1
  91. package/web/assets/{kanban-definition-HUTT4EX6-n0010rmQ.js → kanban-definition-HUTT4EX6-BQHNJgXZ.js} +1 -1
  92. package/web/assets/{linear-C0d0lT8O.js → linear-BPiQCLNk.js} +1 -1
  93. package/web/assets/{mermaid.core-BDVbShyO.js → mermaid.core-CD-KvBjV.js} +4 -4
  94. package/web/assets/{metadata-KV0dpp4G.js → metadata-COJ7fZul.js} +1 -1
  95. package/web/assets/{mindmap-definition-LN4V7U3C--_0ks3GF.js → mindmap-definition-LN4V7U3C-C1L_gyoj.js} +1 -1
  96. package/web/assets/{pegDiagram-2B236MQR-CBoNIpKR.js → pegDiagram-2B236MQR-BDAfItqS.js} +1 -1
  97. package/web/assets/{pieDiagram-ENE6RG2P-MA5tkYh5.js → pieDiagram-ENE6RG2P-CkZYH3Vz.js} +1 -1
  98. package/web/assets/{popover-DBD7FF-W.js → popover-0oA2lLUV.js} +2 -2
  99. package/web/assets/{project-search-dialog-DM1IkSZu.js → project-search-dialog-B2oqMT6h.js} +1 -1
  100. package/web/assets/{quadrantDiagram-ABIIQ3AL-CWT1ryqF.js → quadrantDiagram-ABIIQ3AL-Dy8Al3YZ.js} +1 -1
  101. package/web/assets/{railroadDiagram-RFXS5EU6-ZiLB5FGi.js → railroadDiagram-RFXS5EU6-Dd9_yo7B.js} +1 -1
  102. package/web/assets/{requirementDiagram-TGXJPOKE-CQq9uneq.js → requirementDiagram-TGXJPOKE-DPhIUsbs.js} +1 -1
  103. package/web/assets/{sankeyDiagram-HTMAVEWB-qDG-0JqI.js → sankeyDiagram-HTMAVEWB-B2QkYtub.js} +1 -1
  104. package/web/assets/{search-DNrQA5fF.js → search-C1J0-xiB.js} +1 -1
  105. package/web/assets/select-CtXC_PLC.js +30 -0
  106. package/web/assets/{selection-popup-DmtTeRs2.js → selection-popup-qhlUFzGq.js} +1 -1
  107. package/web/assets/{sequenceDiagram-DBY2YBRQ-CiApurLO.js → sequenceDiagram-DBY2YBRQ-Bx7fcZDx.js} +1 -1
  108. package/web/assets/{sizeCapture-X5ZJPWSS-DZSR5QXm.js → sizeCapture-X5ZJPWSS-CIXIhl_A.js} +1 -1
  109. package/web/assets/{stateDiagram-2N3HPSRC-CjJJR9_z.js → stateDiagram-2N3HPSRC-DCrdAflB.js} +1 -1
  110. package/web/assets/stateDiagram-v2-6OUMAXLB-0KCFLYeQ.js +1 -0
  111. package/web/assets/{swimlanes-5IMT3BWC-CKmo1sg6.js → swimlanes-5IMT3BWC-DA2vc7iZ.js} +2 -2
  112. package/web/assets/swimlanesDiagram-G3AALYLV-CAw3AV84.js +8 -0
  113. package/web/assets/{timeline-definition-FHXFAJF6-D-NMwS3y.js → timeline-definition-FHXFAJF6-lKfJiV9V.js} +1 -1
  114. package/web/assets/{vennDiagram-L72KCM5P-CfL6LBWw.js → vennDiagram-L72KCM5P-DO1q2KzG.js} +1 -1
  115. package/web/assets/{view-context-gyDl_p2V.js → view-context-DXKM3-l1.js} +4 -4
  116. package/web/assets/{viewer-capabilities-Bpp8Uvcg.js → viewer-capabilities-Cig_xM9u.js} +1 -1
  117. package/web/assets/{wardleyDiagram-EHGQE667-DgldMxaj.js → wardleyDiagram-EHGQE667-Dal9LkuZ.js} +1 -1
  118. package/web/assets/{xychartDiagram-FW5EYKEG-CIoAIFX8.js → xychartDiagram-FW5EYKEG-B3dPLPII.js} +1 -1
  119. package/web/index.html +2 -2
  120. package/kernel/packages/api/test/partial-loading.test.ts +0 -43
  121. package/kernel/plugins/calendar/SKILL.md +0 -173
  122. package/kernel/plugins/calendar/eslint.config.js +0 -10
  123. package/kernel/plugins/calendar/package.json +0 -73
  124. package/kernel/plugins/calendar/schema.json +0 -137
  125. package/kernel/plugins/calendar/src/calendar.tsx +0 -328
  126. package/kernel/plugins/calendar/src/client.tsx +0 -139
  127. package/kernel/plugins/calendar/src/context.ts +0 -48
  128. package/kernel/plugins/calendar/src/copy-button.tsx +0 -66
  129. package/kernel/plugins/calendar/src/event-dialog.tsx +0 -270
  130. package/kernel/plugins/calendar/src/index.ts +0 -4
  131. package/kernel/plugins/calendar/src/manifest.ts +0 -7
  132. package/kernel/plugins/calendar/src/parse.ts +0 -610
  133. package/kernel/plugins/calendar/src/server.ts +0 -160
  134. package/kernel/plugins/calendar/src/utils.ts +0 -80
  135. package/kernel/plugins/calendar/src/views.tsx +0 -418
  136. package/kernel/plugins/calendar/test/context.test.mjs +0 -60
  137. package/kernel/plugins/calendar/test/package.test.mjs +0 -43
  138. package/kernel/plugins/calendar/test/parse.test.mjs +0 -392
  139. package/kernel/plugins/calendar/test/server.test.mjs +0 -126
  140. package/kernel/plugins/calendar/tsconfig.json +0 -17
  141. package/kernel/plugins/mail/SKILL.md +0 -97
  142. package/kernel/plugins/mail/eslint.config.js +0 -10
  143. package/kernel/plugins/mail/package.json +0 -79
  144. package/kernel/plugins/mail/src/api.ts +0 -359
  145. package/kernel/plugins/mail/src/bun-ffi.d.ts +0 -14
  146. package/kernel/plugins/mail/src/client.tsx +0 -14
  147. package/kernel/plugins/mail/src/flock.ts +0 -137
  148. package/kernel/plugins/mail/src/folders.ts +0 -37
  149. package/kernel/plugins/mail/src/history.ts +0 -485
  150. package/kernel/plugins/mail/src/index.ts +0 -3
  151. package/kernel/plugins/mail/src/mail-card.tsx +0 -123
  152. package/kernel/plugins/mail/src/mail-conversation.tsx +0 -153
  153. package/kernel/plugins/mail/src/mail-detail-page.tsx +0 -467
  154. package/kernel/plugins/mail/src/mail-hooks.ts +0 -252
  155. package/kernel/plugins/mail/src/mail-page.tsx +0 -109
  156. package/kernel/plugins/mail/src/mail-request.ts +0 -78
  157. package/kernel/plugins/mail/src/mail-send-box.tsx +0 -175
  158. package/kernel/plugins/mail/src/mailos.ts +0 -723
  159. package/kernel/plugins/mail/src/manifest.ts +0 -7
  160. package/kernel/plugins/mail/src/node.ts +0 -171
  161. package/kernel/plugins/mail/src/parse.ts +0 -139
  162. package/kernel/plugins/mail/src/server.ts +0 -125
  163. package/kernel/plugins/mail/src/types.ts +0 -10
  164. package/kernel/plugins/mail/src/viewer.tsx +0 -147
  165. package/kernel/plugins/mail/test/flock.test.mjs +0 -156
  166. package/kernel/plugins/mail/test/folders.test.mjs +0 -138
  167. package/kernel/plugins/mail/test/history.test.mjs +0 -460
  168. package/kernel/plugins/mail/test/mailos.test.mjs +0 -752
  169. package/kernel/plugins/mail/test/node.test.mjs +0 -207
  170. package/kernel/plugins/mail/test/package.test.mjs +0 -54
  171. package/kernel/plugins/mail/test/parse.test.mjs +0 -32
  172. package/kernel/plugins/mail/test/server.test.mjs +0 -116
  173. package/kernel/plugins/mail/test/viewer.test.mjs +0 -192
  174. package/kernel/plugins/mail/tsconfig.json +0 -17
  175. package/kernel/plugins/projects/SKILL.md +0 -73
  176. package/kernel/plugins/projects/eslint.config.js +0 -10
  177. package/kernel/plugins/projects/package.json +0 -70
  178. package/kernel/plugins/projects/src/client.tsx +0 -17
  179. package/kernel/plugins/projects/src/data/model.ts +0 -129
  180. package/kernel/plugins/projects/src/index.ts +0 -17
  181. package/kernel/plugins/projects/src/manifest.ts +0 -7
  182. package/kernel/plugins/projects/src/project-context.ts +0 -41
  183. package/kernel/plugins/projects/src/server.ts +0 -276
  184. package/kernel/plugins/projects/src/ui/project-card.tsx +0 -61
  185. package/kernel/plugins/projects/src/ui/projects-page.tsx +0 -102
  186. package/kernel/plugins/projects/test/package.test.mjs +0 -51
  187. package/kernel/plugins/projects/tsconfig.json +0 -17
  188. package/kernel/plugins/tasks/SKILL.md +0 -341
  189. package/kernel/plugins/tasks/eslint.config.js +0 -10
  190. package/kernel/plugins/tasks/package.json +0 -74
  191. package/kernel/plugins/tasks/schema.json +0 -939
  192. package/kernel/plugins/tasks/src/api.ts +0 -212
  193. package/kernel/plugins/tasks/src/client.tsx +0 -23
  194. package/kernel/plugins/tasks/src/data/parse.ts +0 -544
  195. package/kernel/plugins/tasks/src/data/task-id.ts +0 -56
  196. package/kernel/plugins/tasks/src/data/todo-model.ts +0 -795
  197. package/kernel/plugins/tasks/src/index.ts +0 -34
  198. package/kernel/plugins/tasks/src/manifest.ts +0 -7
  199. package/kernel/plugins/tasks/src/pages/task-detail.tsx +0 -48
  200. package/kernel/plugins/tasks/src/pages/task-list.tsx +0 -88
  201. package/kernel/plugins/tasks/src/server.ts +0 -447
  202. package/kernel/plugins/tasks/src/styles.css +0 -9
  203. package/kernel/plugins/tasks/src/ui/compact-todo-list.tsx +0 -372
  204. package/kernel/plugins/tasks/src/ui/error-details.tsx +0 -78
  205. package/kernel/plugins/tasks/src/ui/task-page.tsx +0 -392
  206. package/kernel/plugins/tasks/src/ui/todo-agent-filter.tsx +0 -36
  207. package/kernel/plugins/tasks/src/ui/todo-filter-bar.tsx +0 -66
  208. package/kernel/plugins/tasks/src/ui/todo-item.tsx +0 -494
  209. package/kernel/plugins/tasks/src/ui/todo-status-filter.tsx +0 -60
  210. package/kernel/plugins/tasks/src/ui/todo-tag-filter.tsx +0 -48
  211. package/kernel/plugins/tasks/src/ui/todo-warnings.tsx +0 -106
  212. package/kernel/plugins/tasks/test/api.test.mjs +0 -99
  213. package/kernel/plugins/tasks/test/folder-sources.test.mjs +0 -46
  214. package/kernel/plugins/tasks/test/package.test.mjs +0 -54
  215. package/kernel/plugins/tasks/test/parse.test.mjs +0 -225
  216. package/kernel/plugins/tasks/test/server.test.mjs +0 -386
  217. package/kernel/plugins/tasks/tsconfig.json +0 -17
  218. package/web/assets/app-DoGr2Zi7.js +0 -2
  219. package/web/assets/channel-uMEjV8qc.js +0 -1
  220. package/web/assets/classDiagram-OUVF2IWQ-fbZocVor.js +0 -1
  221. package/web/assets/classDiagram-v2-EOCWNBFH-fbZocVor.js +0 -1
  222. package/web/assets/client-C6Nxdfif.js +0 -2
  223. package/web/assets/client-CXYfBko5.js +0 -17
  224. package/web/assets/client-CoKtOq-X.js +0 -7
  225. package/web/assets/client-DyRQz5RU.js +0 -53
  226. package/web/assets/client-OY6HUzuD.js +0 -98
  227. package/web/assets/client-YOYWZIFi.js +0 -34
  228. package/web/assets/command-BugZBGXE.js +0 -38
  229. package/web/assets/folder-plugin-view-DsWR1zmQ.js +0 -6
  230. package/web/assets/index-BaRnbYRw.js +0 -1
  231. package/web/assets/index-BexmLxIP.css +0 -1
  232. package/web/assets/index-DDirZMgx.js +0 -1
  233. package/web/assets/note-card-DBfX6gW1.js +0 -6
  234. package/web/assets/select-D8cqNgcp.js +0 -30
  235. package/web/assets/stateDiagram-v2-6OUMAXLB-BpeGSCu9.js +0 -1
  236. package/web/assets/swimlanesDiagram-G3AALYLV-D9RjLKb9.js +0 -8
  237. package/web/assets/use-folder-filter-LQyXns5Q.js +0 -1
@@ -1,123 +0,0 @@
1
- import type { ReactNode } from "react"
2
- import { Folder, Mail } from "lucide-react"
3
-
4
- import type { MailListItem } from "./viewer.tsx"
5
-
6
- function relativeTime(value: string | null) {
7
- if (!value) return "—"
8
- const parsed = Date.parse(value)
9
- if (Number.isNaN(parsed)) return value
10
- const delta = Date.now() - parsed
11
- const minutes = Math.round(delta / 60_000)
12
- if (minutes < 1) return "just now"
13
- if (minutes < 60) return `${minutes}m ago`
14
- const hours = Math.round(minutes / 60)
15
- if (hours < 48) return `${hours}h ago`
16
- const days = Math.round(hours / 24)
17
- return `${days}d ago`
18
- }
19
-
20
- export function MailCard({
21
- actions,
22
- folderLabel,
23
- href,
24
- item,
25
- }: {
26
- actions?: (item: MailListItem) => ReactNode
27
- folderLabel?: string | null
28
- href: string
29
- item: MailListItem
30
- }) {
31
- const recipientGroup = item.to.length
32
- ? { label: "To", items: item.to }
33
- : item.cc.length
34
- ? { label: "CC", items: item.cc }
35
- : item.bcc.length
36
- ? { label: "BCC", items: item.bcc }
37
- : null
38
-
39
- const recipient = item.to[0] ?? ""
40
- const address = /<([^<>]+)>/.exec(recipient)?.[1] ?? recipient
41
- const domain = /^[^\s@<>]+@([a-z0-9.-]+\.[a-z]{2,})$/i
42
- .exec(address.trim())?.[1]
43
- ?.toLowerCase()
44
-
45
- return (
46
- <li className="relative min-w-0">
47
- <a
48
- className="grid grid-cols-[2rem_minmax(0,1fr)] items-start gap-3
49
- rounded-xl border border-[#e7ebe7] bg-white px-3.5 py-2.5 pr-10
50
- text-[#2f382f] no-underline shadow-[0_1px_2px_rgb(31_41_55/0.05)]
51
- hover:bg-[#fafbfa] focus-visible:outline-2
52
- focus-visible:outline-offset-1 focus-visible:outline-[#56725e]"
53
- href={href}
54
- >
55
- <span
56
- aria-hidden="true"
57
- className="relative flex size-8 items-center justify-center rounded-md
58
- bg-[#f3f5f2] text-[#6c7a6d]"
59
- >
60
- <Mail className="size-4" />
61
- {domain ? (
62
- <img
63
- key={domain}
64
- alt=""
65
- className="absolute size-6 rounded-sm bg-[#f3f5f2] object-contain"
66
- height={24}
67
- loading="lazy"
68
- onError={(event) => {
69
- event.currentTarget.style.display = "none"
70
- }}
71
- referrerPolicy="no-referrer"
72
- src={`https://www.google.com/s2/favicons?domain=${encodeURIComponent(domain)}&sz=32`}
73
- width={24}
74
- />
75
- ) : null}
76
- </span>
77
- <div className="grid min-w-0 gap-1">
78
- <span className="line-clamp-2 min-w-0 font-semibold break-words">
79
- {item.subject ?? "(no subject)"}
80
- </span>
81
-
82
- <div className="flex items-start gap-2">
83
- <span
84
- className="shrink-0 text-[0.75rem] whitespace-nowrap
85
- text-[#6c7a6d]"
86
- >
87
- {relativeTime(item.updatedAt ?? item.createdAt)}
88
- </span>
89
- {recipientGroup ? (
90
- <span className="min-w-0 truncate text-[0.82rem] text-[#4a554b]">
91
- {recipientGroup.label}: {recipientGroup.items[0]}
92
- {recipientGroup.items.length > 1
93
- ? ` +${recipientGroup.items.length - 1}`
94
- : ""}
95
- </span>
96
- ) : (
97
- <span className="text-[0.82rem] text-[#6c7a6d]">
98
- No recipients
99
- </span>
100
- )}
101
- </div>
102
- {folderLabel ? (
103
- <span
104
- className="flex min-w-0 items-center gap-1 text-xs text-[#6c7a6d]"
105
- title={item.folder ?? undefined}
106
- >
107
- <Folder aria-hidden="true" className="size-3 shrink-0" />
108
- <span className="truncate">{folderLabel}</span>
109
- </span>
110
- ) : null}
111
- {item.excerpt ? (
112
- <p className="m-0 min-w-0 truncate text-[0.82rem] text-[#6c7a6d]">
113
- {item.excerpt}
114
- </p>
115
- ) : null}
116
- </div>
117
- </a>
118
- {actions ? (
119
- <div className="absolute top-2 right-2">{actions(item)}</div>
120
- ) : null}
121
- </li>
122
- )
123
- }
@@ -1,153 +0,0 @@
1
- import { RefreshCw } from "lucide-react"
2
-
3
- import { BarkdownMarkdown } from "@raggle-ai/markdown"
4
-
5
- import type { ConversationMessagePayload } from "./mail-hooks.js"
6
- import { conversationPanelState, useMailConversation } from "./mail-hooks.js"
7
- import { mailErrorText } from "./mail-request.js"
8
-
9
- function notice(message: string, onRetry: () => void) {
10
- return (
11
- <p className="m-0 flex flex-wrap items-center gap-2 text-sm text-[#6c7a6d]">
12
- <span className="break-words">{message}</span>
13
- <button
14
- type="button"
15
- className="inline-flex items-center gap-1.5 rounded-md border
16
- border-[#dde1dc] bg-white px-2.5 py-1 text-[0.82rem] text-[#4a554b]
17
- hover:bg-[#f3f5f2]"
18
- onClick={onRetry}
19
- >
20
- <RefreshCw className="size-3.5" />
21
- Retry
22
- </button>
23
- </p>
24
- )
25
- }
26
-
27
- function ConversationMessages({
28
- items,
29
- }: {
30
- items: ConversationMessagePayload[]
31
- }) {
32
- return (
33
- <ol className="m-0 grid list-none gap-0 p-0">
34
- {items.map((message, index) => (
35
- <li
36
- className={
37
- index === 0 ? "px-4 py-4" : "border-t border-[#e7ebe7] px-4 py-4"
38
- }
39
- key={message.id}
40
- >
41
- <div className="mb-2 grid gap-1">
42
- <p className="m-0 font-semibold break-words text-[#233025]">
43
- {message.subject ?? "(no subject)"}
44
- </p>
45
- <p className="m-0 text-[0.82rem] text-[#6c7a6d]">
46
- {message.from ?? "Unknown sender"}
47
- {message.date ? ` · ${message.date}` : ""}
48
- </p>
49
- </div>
50
- <div className="prose prose-neutral max-w-none">
51
- <BarkdownMarkdown value={message.body} />
52
- </div>
53
- </li>
54
- ))}
55
- </ol>
56
- )
57
- }
58
-
59
- /**
60
- * The previous-conversation panel. A disabled query is hidden rather than
61
- * stuck loading; partial/not-found/timeout outcomes surface inline errors
62
- * with a retry instead of silently masquerading as an empty conversation.
63
- */
64
- export function MailConversationPanel({
65
- enabled,
66
- folder,
67
- mailId,
68
- }: {
69
- enabled: boolean
70
- folder: string | null | undefined
71
- mailId: string | null | undefined
72
- }) {
73
- const query = useMailConversation(folder, mailId, enabled)
74
- const state = conversationPanelState({
75
- data: query.data,
76
- enabled,
77
- error: query.error,
78
- isPending: query.isPending,
79
- })
80
- const retry = () => void query.refetch()
81
-
82
- if (state.variant === "hidden" || state.variant === "empty") return null
83
- if (state.variant === "loading") {
84
- return <p className="m-0 text-sm text-[#6c7a6d]">Loading conversation…</p>
85
- }
86
- if (state.variant === "error") {
87
- return (
88
- <p
89
- className="m-0 flex flex-wrap items-center gap-2 text-sm text-[#9c3a3a]"
90
- >
91
- <span className="break-words">
92
- Could not load the conversation. {mailErrorText(query.error)}
93
- </span>
94
- <RetryInline onRetry={retry} />
95
- </p>
96
- )
97
- }
98
-
99
- const items = query.data?.items ?? []
100
-
101
- return (
102
- <section
103
- className="overflow-hidden rounded-xl border border-[#e7ebe7] bg-white
104
- shadow-[0_1px_2px_rgb(31_41_55/0.05)]"
105
- >
106
- <header className="border-b border-[#e7ebe7] bg-[#fbfcfb] px-4 py-3">
107
- <h2
108
- className="m-0 text-[0.75rem] font-medium tracking-wide text-[#6c7a6d]
109
- uppercase"
110
- >
111
- Previous conversation
112
- </h2>
113
- </header>
114
-
115
- {items.length ? <ConversationMessages items={items} /> : null}
116
-
117
- <footer className="border-t border-[#e7ebe7] bg-[#fbfcfb] px-4 py-3">
118
- {state.variant === "partial"
119
- ? notice(
120
- `Some earlier messages could not be loaded (${state.missing}).`,
121
- retry,
122
- )
123
- : null}
124
- {state.variant === "not-found"
125
- ? notice("Earlier messages could not be found.", retry)
126
- : null}
127
- {state.variant === "timeout"
128
- ? notice("Loading earlier messages timed out.", retry)
129
- : null}
130
- {state.variant === "ok" && items.length ? (
131
- <p className="m-0 text-[0.82rem] text-[#6c7a6d]">
132
- Thread loaded from references.
133
- </p>
134
- ) : null}
135
- </footer>
136
- </section>
137
- )
138
- }
139
-
140
- function RetryInline({ onRetry }: { onRetry: () => void }) {
141
- return (
142
- <button
143
- type="button"
144
- className="inline-flex items-center gap-1.5 rounded-md border
145
- border-[#dde1dc] bg-white px-2.5 py-1 text-[0.82rem] text-[#4a554b]
146
- hover:bg-[#f3f5f2]"
147
- onClick={onRetry}
148
- >
149
- <RefreshCw className="size-3.5" />
150
- Retry
151
- </button>
152
- )
153
- }