@heyramzi/ui 2.8.0 → 2.10.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 (426) hide show
  1. package/COMPONENTS.md +1 -1
  2. package/README.md +1 -1
  3. package/dist/agents/helpers.js +52 -0
  4. package/dist/agents/index.js +3 -0
  5. package/dist/agents/page-state.js +65 -0
  6. package/dist/agents/types.js +1 -0
  7. package/dist/agents/vendor/color.js +149 -0
  8. package/dist/agents/vendor/draw.js +548 -0
  9. package/dist/agents/vendor/engine.js +632 -0
  10. package/dist/agents/vendor/mesh.js +727 -0
  11. package/dist/agents/vendor/plastic.js +3273 -0
  12. package/dist/agents/vendor/presets.js +171 -0
  13. package/dist/agents/vendor/shapes.js +24 -0
  14. package/dist/agents/vendor/ticker.js +56 -0
  15. package/dist/agents/vendor/types.js +0 -0
  16. package/dist/agents/vendor/wear.js +1525 -0
  17. package/dist/ai/ai-button/index.js +2 -0
  18. package/dist/ai/confirmation/confirmation-context.svelte.js +12 -0
  19. package/dist/ai/confirmation/index.js +9 -0
  20. package/dist/ai/generation-progress/index.js +2 -0
  21. package/dist/ai/index.js +11 -0
  22. package/dist/ai/loading-state/index.js +3 -0
  23. package/dist/ai/prompt-input/index.js +6 -0
  24. package/dist/ai/reasoning/index.js +4 -0
  25. package/dist/ai/reasoning/reasoning-context.svelte.js +12 -0
  26. package/dist/ai/response/index.js +3 -0
  27. package/dist/ai/suggestion/index.js +3 -0
  28. package/dist/ai/thinking-dots/index.js +3 -0
  29. package/dist/ai/typing-dots/index.js +2 -0
  30. package/dist/ai/voice-waveform/index.js +3 -0
  31. package/dist/animations/text-swap.js +30 -0
  32. package/dist/brand/index.js +65 -0
  33. package/dist/canvas/card/resize.js +10 -0
  34. package/dist/canvas/edges/edge-path.js +284 -0
  35. package/dist/canvas/editor/context-menu.js +42 -0
  36. package/dist/canvas/editor/dispatch.svelte.js +157 -0
  37. package/dist/canvas/editor/editor-context.js +8 -0
  38. package/dist/canvas/editor/editor-mode.js +0 -0
  39. package/dist/canvas/editor/frame.js +87 -0
  40. package/dist/canvas/editor/hand-context.js +8 -0
  41. package/dist/canvas/editor/history-core.js +221 -0
  42. package/dist/canvas/editor/keymap.js +193 -0
  43. package/dist/canvas/editor/layout-actions.js +170 -0
  44. package/dist/canvas/editor/lock.js +65 -0
  45. package/dist/canvas/editor/rebase.js +279 -0
  46. package/dist/canvas/editor/style.js +174 -0
  47. package/dist/canvas/editor/text-field-context.js +8 -0
  48. package/dist/canvas/editor/z-order.js +82 -0
  49. package/dist/canvas/headless/alignment.js +20 -0
  50. package/dist/canvas/headless/break-apart-find.js +324 -0
  51. package/dist/canvas/headless/break-apart-pieces.js +74 -0
  52. package/dist/canvas/headless/break-apart-plan.js +378 -0
  53. package/dist/canvas/headless/break-apart-style.js +93 -0
  54. package/dist/canvas/headless/break-apart.js +206 -0
  55. package/dist/canvas/headless/canvas-cleanup.js +70 -0
  56. package/dist/canvas/headless/edge-anchors.js +134 -0
  57. package/dist/canvas/headless/edge-memo.js +28 -0
  58. package/dist/canvas/headless/edge-serialization.js +31 -0
  59. package/dist/canvas/headless/figure-geometry.js +331 -0
  60. package/dist/canvas/headless/fit-viewport.js +82 -0
  61. package/dist/canvas/headless/grid.js +96 -0
  62. package/dist/canvas/headless/icon-node.js +45 -0
  63. package/dist/canvas/headless/index.js +1 -0
  64. package/dist/canvas/headless/linkify.js +25 -0
  65. package/dist/canvas/headless/pen-marks.js +115 -0
  66. package/dist/canvas/headless/sketch.js +250 -0
  67. package/dist/canvas/headless/snap-guides.js +100 -0
  68. package/dist/canvas/headless/svg-figure.js +137 -0
  69. package/dist/canvas/headless/table-layout.js +161 -0
  70. package/dist/canvas/index.js +25 -0
  71. package/dist/canvas/lod/lod-mode.svelte.js +22 -0
  72. package/dist/canvas/lod/render-all.svelte.js +45 -0
  73. package/dist/canvas/ops/arrange.js +83 -0
  74. package/dist/canvas/ops/ops.js +318 -0
  75. package/dist/canvas/pen/colors.js +41 -0
  76. package/dist/canvas/pen/eraser.js +35 -0
  77. package/dist/canvas/pen/geometry.js +143 -0
  78. package/dist/canvas/pen/index.js +9 -0
  79. package/dist/canvas/pen/ops.js +15 -0
  80. package/dist/canvas/pen/pen-session.js +171 -0
  81. package/dist/canvas/pen/plugin.js +129 -0
  82. package/dist/canvas/pen/shapes.js +80 -0
  83. package/dist/canvas/pen/stroke-path.js +37 -0
  84. package/dist/canvas/pen/types.js +30 -0
  85. package/dist/canvas/pen/ui.js +20 -0
  86. package/dist/canvas/plugin.js +51 -0
  87. package/dist/canvas/screen/glyphs.js +24 -0
  88. package/dist/canvas/screen/labels.js +24 -0
  89. package/dist/canvas/screen/parts.js +140 -0
  90. package/dist/canvas/screen/plugin.js +71 -0
  91. package/dist/canvas/screen/types.js +44 -0
  92. package/dist/canvas/screen/ui.js +13 -0
  93. package/dist/canvas/test-utils.js +18 -0
  94. package/dist/canvas/types.js +0 -0
  95. package/dist/canvas/ui/forward-wheel.js +27 -0
  96. package/dist/canvas/ui/icons.js +133 -0
  97. package/dist/canvas/ui/place-panel.js +57 -0
  98. package/dist/canvas/ui/shortcut-tip.js +18 -0
  99. package/dist/canvas/ui/tools.js +411 -0
  100. package/dist/charts/dashboard/chart.js +1 -0
  101. package/dist/charts/dashboard/data-table.js +7 -0
  102. package/dist/charts/dashboard/index.js +13 -0
  103. package/dist/charts/dashboard/windows.js +5 -0
  104. package/dist/charts/edge-fade.js +7 -0
  105. package/dist/charts/hover-band.js +13 -0
  106. package/dist/charts/index.js +19 -0
  107. package/dist/charts/motion.js +15 -0
  108. package/dist/charts/primitives/chart-utils.js +22 -0
  109. package/dist/charts/primitives/index.js +4 -0
  110. package/dist/components/copy/clipboard.js +38 -0
  111. package/dist/components/copy/copied.svelte.js +26 -0
  112. package/dist/components/copy/index.js +3 -0
  113. package/dist/components/data-table/data-table.js +55 -0
  114. package/dist/components/data-table/index.js +7 -0
  115. package/dist/components/docs/index.js +3 -0
  116. package/dist/components/docs/scroll-spy.svelte.js +71 -0
  117. package/dist/components/field-row/index.js +1 -0
  118. package/dist/components/hold-to-confirm/index.js +1 -0
  119. package/dist/components/icon/index.js +1 -0
  120. package/dist/components/language-flag/index.js +1 -0
  121. package/dist/components/list-page/filter-section.js +4 -0
  122. package/dist/components/list-page/index.js +25 -0
  123. package/dist/components/list-page/list-table.js +5 -0
  124. package/dist/components/list-page/queue-rail.js +3 -0
  125. package/dist/components/list-page/section-host.js +8 -0
  126. package/dist/components/list-page/step.js +5 -0
  127. package/dist/components/list-page/types.js +0 -0
  128. package/dist/components/locale-switch/index.js +1 -0
  129. package/dist/components/mark/index.js +1 -0
  130. package/dist/components/open-in/index.js +1 -0
  131. package/dist/components/picker/index.js +3 -0
  132. package/dist/components/picker/trigger.js +33 -0
  133. package/dist/components/picker/types.js +0 -0
  134. package/dist/components/section-card/index.js +1 -0
  135. package/dist/components/section-header/index.js +2 -0
  136. package/dist/components/segmented/collapse.js +32 -0
  137. package/dist/components/segmented/index.js +8 -0
  138. package/dist/components/segmented/segmented.js +50 -0
  139. package/dist/components/star-rating-input/index.js +2 -0
  140. package/dist/components/svg/index.js +1 -0
  141. package/dist/components/table-view/index.js +1 -0
  142. package/dist/components/table-view/types.js +0 -0
  143. package/dist/components/tags-input/index.js +2 -0
  144. package/dist/components/tags-input/tags.js +90 -0
  145. package/dist/components/theme/index.js +3 -0
  146. package/dist/components/toolbar/index.js +3 -0
  147. package/dist/components/toolbar/toolbar-trigger.js +4 -0
  148. package/dist/editor/anchors.js +17 -0
  149. package/dist/editor/block-id.js +62 -0
  150. package/dist/editor/block-ops.js +105 -0
  151. package/dist/editor/doc-blocks.js +181 -0
  152. package/dist/editor/extensions.js +200 -0
  153. package/dist/editor/index.js +4 -0
  154. package/dist/editor/markdown-test-helpers.js +6 -0
  155. package/dist/editor/markdown.js +486 -0
  156. package/dist/editor/serializer.js +268 -0
  157. package/dist/editor/slash-items.js +104 -0
  158. package/dist/editor/youtube-url.js +27 -0
  159. package/dist/effects/animated-beam/index.js +1 -0
  160. package/dist/effects/animated-beam/path-calculator.svelte.js +42 -0
  161. package/dist/effects/animated-beam/types.js +0 -0
  162. package/dist/effects/border-beam/css.js +420 -0
  163. package/dist/effects/border-beam/presets.js +1792 -0
  164. package/dist/effects/border-beam/register-properties.js +39 -0
  165. package/dist/effects/border-beam/types.js +0 -0
  166. package/dist/effects/image-comparison/compare.js +4 -0
  167. package/dist/effects/image-reveal/index.js +1 -0
  168. package/dist/effects/image-reveal/types.js +0 -0
  169. package/dist/effects/magnetic/magnetic.js +54 -0
  170. package/dist/effects/reveal/index.js +4 -0
  171. package/dist/effects/reveal/observe.js +43 -0
  172. package/dist/effects/reveal/types.js +0 -0
  173. package/dist/effects/shader-gradient/color.js +34 -0
  174. package/dist/effects/shader-gradient/index.js +1 -0
  175. package/dist/effects/shader-gradient/renderer.js +320 -0
  176. package/dist/effects/shader-gradient/shaders.js +280 -0
  177. package/dist/effects/shader-gradient/types.js +0 -0
  178. package/dist/icons/apple-symbol-exports.js +126 -0
  179. package/dist/icons/sf-symbols.js +465 -0
  180. package/dist/icons/trades.js +34 -0
  181. package/dist/inbox/index.js +4 -0
  182. package/dist/inbox/logic.js +156 -0
  183. package/dist/inbox/types.js +46 -0
  184. package/dist/index.js +18 -0
  185. package/dist/lib/arrive.js +13 -0
  186. package/dist/lib/icon-types.js +0 -0
  187. package/dist/lib/initials.js +17 -0
  188. package/dist/lib/layout.js +1 -0
  189. package/dist/lib/panel.js +3 -0
  190. package/dist/lib/result.js +26 -0
  191. package/dist/lib/sliding-pill.js +45 -0
  192. package/dist/lib/theme-transition.js +53 -0
  193. package/dist/lib/tone.js +32 -0
  194. package/dist/lib/utils.js +5 -0
  195. package/dist/onboarding/define-tours.js +28 -0
  196. package/dist/onboarding/index.js +4 -0
  197. package/dist/onboarding/onboarding.svelte.js +15 -0
  198. package/dist/onboarding/pick.js +16 -0
  199. package/dist/onboarding/stores.js +50 -0
  200. package/dist/onboarding/types.js +1 -0
  201. package/dist/onboarding/wait.js +25 -0
  202. package/dist/panel/index.js +1 -0
  203. package/dist/panel/side-panel-types.js +0 -0
  204. package/dist/record/demo-data.js +512 -0
  205. package/dist/record/fields.js +148 -0
  206. package/dist/record/format.js +97 -0
  207. package/dist/record/gutter.js +1 -0
  208. package/dist/record/index.js +15 -0
  209. package/dist/record/kinds.js +110 -0
  210. package/dist/record/logic.js +255 -0
  211. package/dist/record/types.js +52 -0
  212. package/dist/shadcn/accordion/index.js +5 -0
  213. package/dist/shadcn/alert/index.js +5 -0
  214. package/dist/shadcn/alert-dialog/index.js +12 -0
  215. package/dist/shadcn/attachment/index.js +10 -0
  216. package/dist/shadcn/avatar/index.js +7 -0
  217. package/dist/shadcn/badge/index.js +2 -0
  218. package/dist/shadcn/breadcrumb/index.js +8 -0
  219. package/dist/shadcn/bubble/index.js +5 -0
  220. package/dist/shadcn/button/index.js +2 -0
  221. package/dist/shadcn/calendar/index.js +19 -0
  222. package/dist/shadcn/card/index.js +8 -0
  223. package/dist/shadcn/checkbox/index.js +2 -0
  224. package/dist/shadcn/code-block/index.js +9 -0
  225. package/dist/shadcn/collapsible/index.js +4 -0
  226. package/dist/shadcn/command/index.js +13 -0
  227. package/dist/shadcn/context-menu/index.js +17 -0
  228. package/dist/shadcn/dialog/index.js +11 -0
  229. package/dist/shadcn/dropdown-menu/index.js +19 -0
  230. package/dist/shadcn/dropdown-menu/menu-item.js +23 -0
  231. package/dist/shadcn/empty/index.js +7 -0
  232. package/dist/shadcn/field/index.js +12 -0
  233. package/dist/shadcn/hooks/highlighter.js +92 -0
  234. package/dist/shadcn/hooks/is-mobile.svelte.js +7 -0
  235. package/dist/shadcn/hooks/use-highlighted-code.svelte.js +65 -0
  236. package/dist/shadcn/hover-card/index.js +5 -0
  237. package/dist/shadcn/input/index.js +3 -0
  238. package/dist/shadcn/input-otp/index.js +5 -0
  239. package/dist/shadcn/kbd/index.js +3 -0
  240. package/dist/shadcn/label/index.js +2 -0
  241. package/dist/shadcn/marker/index.js +4 -0
  242. package/dist/shadcn/message/index.js +7 -0
  243. package/dist/shadcn/message-scroller/index.js +8 -0
  244. package/dist/shadcn/popover/index.js +9 -0
  245. package/dist/shadcn/progress/index.js +2 -0
  246. package/dist/shadcn/progress/tone.js +11 -0
  247. package/dist/shadcn/radio-group/index.js +3 -0
  248. package/dist/shadcn/scroll-area/index.js +3 -0
  249. package/dist/shadcn/select/index.js +12 -0
  250. package/dist/shadcn/separator/index.js +2 -0
  251. package/dist/shadcn/sheet/index.js +11 -0
  252. package/dist/shadcn/sidebar/constants.js +6 -0
  253. package/dist/shadcn/sidebar/context.svelte.js +38 -0
  254. package/dist/shadcn/sidebar/index.js +25 -0
  255. package/dist/shadcn/skeleton/index.js +2 -0
  256. package/dist/shadcn/slider/index.js +2 -0
  257. package/dist/shadcn/sonner/index.js +1 -0
  258. package/dist/shadcn/spinner/index.js +1 -0
  259. package/dist/shadcn/switch/index.js +2 -0
  260. package/dist/shadcn/table/index.js +9 -0
  261. package/dist/shadcn/tabs/index.js +5 -0
  262. package/dist/shadcn/textarea/index.js +2 -0
  263. package/dist/shadcn/toggle/index.js +3 -0
  264. package/dist/shadcn/toggle-group/index.js +3 -0
  265. package/dist/shadcn/tooltip/context.js +8 -0
  266. package/dist/shadcn/tooltip/index.js +6 -0
  267. package/dist/shadcn/trace/index.js +9 -0
  268. package/dist/slides/bridges.js +66 -0
  269. package/dist/slides/deck-controller.svelte.js +221 -0
  270. package/dist/slides/export/capture.js +81 -0
  271. package/dist/slides/export/ffmpeg.js +85 -0
  272. package/dist/slides/export/index.js +4 -0
  273. package/dist/slides/export/launch.js +8 -0
  274. package/dist/slides/export/pdf.js +78 -0
  275. package/dist/slides/export/types.js +0 -0
  276. package/dist/slides/index.js +7 -0
  277. package/dist/slides/labels.js +26 -0
  278. package/dist/slides/layout.js +47 -0
  279. package/dist/slides/model.js +9 -0
  280. package/dist/slides/navigation.js +89 -0
  281. package/dist/slides/types.js +6 -0
  282. package/dist/status/define-statuses.js +16 -0
  283. package/dist/status/index.js +4 -0
  284. package/dist/status/status-types.js +0 -0
  285. package/dist/test-setup.js +26 -0
  286. package/dist/thread/index.js +3 -0
  287. package/dist/thread/logic.js +94 -0
  288. package/dist/thread/types.js +23 -0
  289. package/dist/work/board-order.js +109 -0
  290. package/dist/work/dates.js +19 -0
  291. package/dist/work/detail/detail-types.js +20 -0
  292. package/dist/work/docs/edited.js +39 -0
  293. package/dist/work/docs/index.js +7 -0
  294. package/dist/work/docs/labels.js +38 -0
  295. package/dist/work/docs/menu.js +121 -0
  296. package/dist/work/docs/outline.js +39 -0
  297. package/dist/work/gantt/logic.js +260 -0
  298. package/dist/work/inbox/inbox-logic.js +94 -0
  299. package/dist/work/inbox/inbox-statuses.js +86 -0
  300. package/dist/work/inbox/inbox-types.js +0 -0
  301. package/dist/work/inbox/index.js +1 -0
  302. package/dist/work/index.js +21 -0
  303. package/dist/work/kanban-drag.js +25 -0
  304. package/dist/work/kanban-types.js +0 -0
  305. package/dist/work/presets/sales.js +35 -0
  306. package/dist/work/reorder.js +10 -0
  307. package/dist/work/task-types.js +0 -0
  308. package/dist/work/time/duration.js +60 -0
  309. package/dist/work/time/time-types.js +25 -0
  310. package/dist/work/use-kanban-dnd.svelte.js +128 -0
  311. package/package.json +102 -76
  312. package/src/agents/vendor/draw.ts +4 -4
  313. package/src/canvas/headless/canvas-cleanup.test.ts +1 -1
  314. package/src/canvas/ops/ops.ts +1 -1
  315. package/src/charts/area-chart.svelte +11 -1
  316. package/src/charts/bar-chart.svelte +18 -3
  317. package/src/charts/line-chart.svelte +11 -1
  318. package/src/components/data-table/data-table.ts +4 -5
  319. package/src/components/data-table/pagination.svelte +5 -3
  320. package/src/components/docs/on-this-page.svelte +82 -5
  321. package/src/components/docs/scroll-spy.svelte.ts +6 -1
  322. package/src/components/list-page/detail-header.svelte +7 -3
  323. package/src/components/list-page/empty-state.svelte +3 -1
  324. package/src/components/list-page/filter-popover.svelte +2 -2
  325. package/src/components/list-page/rail-row.svelte +5 -2
  326. package/src/components/mark/mark.svelte +2 -1
  327. package/src/components/section-card/section-card.svelte +3 -1
  328. package/src/components/section-header/section-header.svelte +5 -5
  329. package/src/components/segmented/segment.svelte +1 -1
  330. package/src/components/table-view/table-view.svelte +6 -1
  331. package/src/components/tags-input/tags-input.svelte +1 -1
  332. package/src/components/toolbar/toolbar-trigger.ts +8 -2
  333. package/src/components/toolbar/toolbar.svelte +1 -1
  334. package/src/editor/anchors.ts +28 -0
  335. package/src/editor/doc-blocks.ts +168 -0
  336. package/src/editor/doc-page.css +389 -0
  337. package/src/editor/editor.svelte +47 -5
  338. package/src/editor/extensions.ts +26 -2
  339. package/src/editor/markdown.ts +27 -2
  340. package/src/editor/slash-items.ts +18 -0
  341. package/src/icons/trades.ts +1 -1
  342. package/src/inbox/README.md +6 -4
  343. package/src/inbox/inbox.test.ts +1 -1
  344. package/src/inbox/index.ts +2 -2
  345. package/src/inbox/logic.ts +29 -5
  346. package/src/inbox/thread-inbox.svelte +219 -92
  347. package/src/inbox/types.ts +27 -1
  348. package/src/lib/initials.test.ts +25 -0
  349. package/src/lib/initials.ts +29 -0
  350. package/src/modules.test.ts +4 -64
  351. package/src/panel/README.md +1 -1
  352. package/src/record/README.md +1 -1
  353. package/src/record/demo-data.ts +4 -4
  354. package/src/record/info-list.svelte +5 -4
  355. package/src/record/next-up.svelte +1 -1
  356. package/src/record/project-list.svelte +1 -1
  357. package/src/record/record-demo.svelte +2 -2
  358. package/src/record/steps-rail.svelte +3 -3
  359. package/src/shadcn/badge/badge.svelte +1 -1
  360. package/src/shadcn/card/card-title.svelte +1 -5
  361. package/src/shadcn/empty/empty-description.svelte +1 -1
  362. package/src/shadcn/progress/progress.svelte +8 -1
  363. package/src/shadcn/table/table-cell.svelte +10 -2
  364. package/src/status/README.md +1 -1
  365. package/src/thread/README.md +2 -0
  366. package/src/thread/index.ts +9 -1
  367. package/src/thread/logic.ts +33 -3
  368. package/src/thread/thread-body.svelte +37 -0
  369. package/src/thread/thread-events.svelte +30 -0
  370. package/src/thread/thread.svelte +74 -59
  371. package/src/thread/types.ts +21 -0
  372. package/src/{tasks → work}/README.md +11 -8
  373. package/src/{tasks → work}/detail/task-thread.svelte +8 -15
  374. package/src/work/docs/doc-editor-page.svelte +194 -0
  375. package/src/work/docs/doc-menu.svelte +333 -0
  376. package/src/work/docs/docs-demo.svelte +227 -0
  377. package/src/work/docs/edited-chip.svelte +125 -0
  378. package/src/work/docs/edited.ts +54 -0
  379. package/src/work/docs/index.ts +38 -0
  380. package/src/work/docs/labels.ts +70 -0
  381. package/src/work/docs/menu.ts +127 -0
  382. package/src/work/docs/outline.ts +60 -0
  383. package/src/{tasks → work}/gantt/gantt-group-row.svelte +1 -1
  384. package/src/{tasks → work}/inbox/inbox-card.svelte +113 -50
  385. package/src/work/inbox/inbox-logic.ts +98 -0
  386. package/src/work/inbox/inbox-trace.svelte +58 -0
  387. package/src/{tasks → work}/inbox/inbox-types.ts +2 -0
  388. package/src/{tasks → work}/index.ts +0 -10
  389. package/src/{tasks → work}/kanban-board.svelte +1 -1
  390. package/src/{tasks → work}/task-list.svelte +1 -1
  391. package/src/{tasks → work}/time/time-tracker.svelte +2 -5
  392. package/src/tasks/inbox/inbox-logic.ts +0 -21
  393. package/src/tasks/inbox/inbox-trace.svelte +0 -51
  394. /package/src/{tasks → work}/ambient.d.ts +0 -0
  395. /package/src/{tasks → work}/board-order.ts +0 -0
  396. /package/src/{tasks → work}/dates.ts +0 -0
  397. /package/src/{tasks → work}/demo.svelte +0 -0
  398. /package/src/{tasks → work}/detail/detail-demo.svelte +0 -0
  399. /package/src/{tasks → work}/detail/detail-types.ts +0 -0
  400. /package/src/{tasks → work}/detail/task-chip.svelte +0 -0
  401. /package/src/{tasks → work}/detail/task-detail.svelte +0 -0
  402. /package/src/{tasks → work}/detail/task-property.svelte +0 -0
  403. /package/src/{tasks → work}/gantt/gantt-bar.svelte +0 -0
  404. /package/src/{tasks → work}/gantt/gantt-grid.svelte +0 -0
  405. /package/src/{tasks → work}/gantt/gantt-header.svelte +0 -0
  406. /package/src/{tasks → work}/gantt/gantt-task-row.svelte +0 -0
  407. /package/src/{tasks → work}/gantt/gantt.css +0 -0
  408. /package/src/{tasks → work}/gantt/gantt.test.ts +0 -0
  409. /package/src/{tasks → work}/gantt/logic.test.ts +0 -0
  410. /package/src/{tasks → work}/gantt/logic.ts +0 -0
  411. /package/src/{tasks → work}/inbox/inbox-draft.svelte +0 -0
  412. /package/src/{tasks → work}/inbox/inbox-statuses.ts +0 -0
  413. /package/src/{tasks → work}/inbox/index.ts +0 -0
  414. /package/src/{tasks → work}/kanban-column.svelte +0 -0
  415. /package/src/{tasks → work}/kanban-drag.ts +0 -0
  416. /package/src/{tasks → work}/kanban-types.ts +0 -0
  417. /package/src/{tasks → work}/presets/sales.ts +0 -0
  418. /package/src/{tasks → work}/reorder.ts +0 -0
  419. /package/src/{tasks → work}/task-gantt.svelte +0 -0
  420. /package/src/{tasks → work}/task-types.ts +0 -0
  421. /package/src/{tasks → work}/time/duration.ts +0 -0
  422. /package/src/{tasks → work}/time/time-chip.svelte +0 -0
  423. /package/src/{tasks → work}/time/time-dot.svelte +0 -0
  424. /package/src/{tasks → work}/time/time-ring.svelte +0 -0
  425. /package/src/{tasks → work}/time/time-types.ts +0 -0
  426. /package/src/{tasks → work}/use-kanban-dnd.svelte.ts +0 -0
@@ -1,41 +1,10 @@
1
1
  import { existsSync, readFileSync } from "node:fs";
2
2
  import { dirname, join } from "node:path";
3
3
  import { fileURLToPath } from "node:url";
4
- import { describe, expect, it, vi } from "vite-plus/test";
5
- import * as status from "./status/index.js";
6
- import * as panel from "./panel/index.js";
4
+ import { describe, expect, it } from "vite-plus/test";
7
5
  import * as record from "./record/index.js";
8
6
  import * as inbox from "./inbox/index.js";
9
7
  import * as thread from "./thread/index.js";
10
- import type {
11
- PanelStat as FromTasksPanelStat,
12
- SidePanelWidth as FromTasksWidth,
13
- StatusDef as FromTasksStatusDef,
14
- StatusDotVariant as FromTasksVariant,
15
- StatusId as FromTasksId,
16
- StatusMap as FromTasksMap,
17
- Statuses as FromTasksStatuses,
18
- } from "./tasks/index.js";
19
- import type { PanelStat, SidePanelWidth } from "./panel/index.js";
20
- import type {
21
- StatusDef,
22
- StatusDotVariant,
23
- StatusId,
24
- StatusMap,
25
- Statuses,
26
- } from "./status/index.js";
27
-
28
- // Both spellings of every moved type have to be the same type.
29
- type Same<A, B> = [A] extends [B] ? ([B] extends [A] ? true : false) : false;
30
- const sameTypes: [
31
- Same<PanelStat, FromTasksPanelStat>,
32
- Same<SidePanelWidth, FromTasksWidth>,
33
- Same<StatusDef, FromTasksStatusDef>,
34
- Same<StatusDotVariant, FromTasksVariant>,
35
- Same<StatusId<{ a: StatusDef }>, FromTasksId<{ a: StatusDef }>>,
36
- Same<StatusMap, FromTasksMap>,
37
- Same<Statuses, FromTasksStatuses>,
38
- ] = [true, true, true, true, true, true, true];
39
8
 
40
9
  const pkg = JSON.parse(
41
10
  readFileSync(join(dirname(fileURLToPath(import.meta.url)), "..", "package.json"), "utf8"),
@@ -44,23 +13,6 @@ const pkg = JSON.parse(
44
13
  };
45
14
 
46
15
  describe("module split", () => {
47
- it("keeps every moved name on tasks, the same object as on its new module", async () => {
48
- // The kanban board reads matchMedia on import, and jsdom has none.
49
- vi.stubGlobal("matchMedia", () => ({
50
- matches: false,
51
- addEventListener() {},
52
- removeEventListener() {},
53
- }));
54
- const tasks = await import("./tasks/index.js");
55
- expect(sameTypes).toHaveLength(7);
56
- expect(tasks.StatusBadge).toBe(status.StatusBadge);
57
- expect(tasks.StatusDot).toBe(status.StatusDot);
58
- expect(tasks.StatusIcon).toBe(status.StatusIcon);
59
- expect(tasks.defineStatuses).toBe(status.defineStatuses);
60
- expect(tasks.StatusBadge).toBeDefined();
61
- expect(tasks.SidePanel).toBe(panel.SidePanel);
62
- });
63
-
64
16
  it("holds the record page's names", () => {
65
17
  expect(record.RecordShell).toBeDefined();
66
18
  expect(record.DEFAULT_RECORD_LABELS).toBeDefined();
@@ -84,22 +36,10 @@ describe("module split", () => {
84
36
  expect(missing).toEqual([]);
85
37
  });
86
38
 
87
- it("keeps the old subpaths and adds the new ones", () => {
88
- for (const name of [
89
- "./tasks",
90
- "./tasks/status",
91
- "./tasks/status-dot",
92
- "./tasks/statuses",
93
- "./tasks/side-panel",
94
- "./tasks/record",
95
- "./tasks/inbox",
96
- "./status",
97
- "./panel",
98
- "./record",
99
- "./thread",
100
- "./inbox",
101
- ]) {
39
+ it("exports each module once, under its own name", () => {
40
+ for (const name of ["./work", "./status", "./panel", "./record", "./thread", "./inbox"]) {
102
41
  expect(pkg.exports[name], name).toBeDefined();
103
42
  }
43
+ expect(Object.keys(pkg.exports).filter((name) => name.startsWith("./tasks"))).toEqual([]);
104
44
  });
105
45
  });
@@ -1,5 +1,5 @@
1
1
  # @heyramzi/ui/panel
2
2
 
3
- `SidePanel`, a sheet for one record: badges, links out to other tools, a copy-a-prompt handoff and a stats strip. `PanelStat` types one stat. It used to live in `@heyramzi/ui/tasks`, which still re-exports both, and `tasks/side-panel` still resolves.
3
+ `SidePanel`, a sheet for one record: badges, links out to other tools, a copy-a-prompt handoff and a stats strip. `PanelStat` types one stat. It used to live in `@heyramzi/ui/work`, which still re-exports both, and `tasks/side-panel` still resolves.
4
4
 
5
5
  Exports: `SidePanel` and the types `PanelStat`, `SidePanelWidth`.
@@ -1,3 +1,3 @@
1
1
  # @heyramzi/ui/record
2
2
 
3
- The page shell for a project or a client record: header, where-we-are, next up, stats, steps rail, timeline, project list and field sections. It used to live at `@heyramzi/ui/tasks/record`, which still resolves to the same module.
3
+ The page shell for a project or a client record: header, where-we-are, next up, stats, steps rail, timeline, project list and field sections.
@@ -185,7 +185,7 @@ export const websiteEvents: RecordEvent[] = [
185
185
  { label: "Length", value: "45 min" },
186
186
  { label: "With", value: "Jane Roe, Tom Bell" },
187
187
  ],
188
- href: "#call-scoping",
188
+ href: "#",
189
189
  },
190
190
  {
191
191
  id: "w3",
@@ -233,7 +233,7 @@ export const websiteEvents: RecordEvent[] = [
233
233
  export const website: RecordSummary = {
234
234
  id: "p-web",
235
235
  name: "Website rebuild",
236
- href: "#project-web",
236
+ href: "#",
237
237
  stageKey: "sent",
238
238
  value: 12000,
239
239
  currency: "EUR",
@@ -254,7 +254,7 @@ export const website: RecordSummary = {
254
254
  export const audit: RecordSummary = {
255
255
  id: "p-audit",
256
256
  name: "Brand audit",
257
- href: "#project-audit",
257
+ href: "#",
258
258
  stageKey: "lost",
259
259
  stageDetail: "Price",
260
260
  value: 4500,
@@ -272,7 +272,7 @@ export const audit: RecordSummary = {
272
272
  export const portal: RecordSummary = {
273
273
  id: "p-portal",
274
274
  name: "Booking portal",
275
- href: "#project-portal",
275
+ href: "#",
276
276
  stageKey: "paid",
277
277
  value: 18000,
278
278
  paid: 18000,
@@ -166,7 +166,7 @@
166
166
  {#snippet display(row: InfoRow, clamp = false)}
167
167
  {#if row.chips?.length}
168
168
  <span class="flex flex-wrap items-center gap-1">
169
- {#each row.chips as chip (chip.label)}
169
+ {#each row.chips as chip, i (i)}
170
170
  <StatusBadge tone={chip.tone ?? "neutral"} capitalize={false}>{chip.label}</StatusBadge>
171
171
  {/each}
172
172
  </span>
@@ -175,6 +175,7 @@
175
175
  {:else if row.href && row.value}
176
176
  <a
177
177
  href={row.href}
178
+ title={row.value}
178
179
  class={cn(
179
180
  "min-w-0 truncate text-sm font-medium underline-offset-2 hover:underline",
180
181
  clamp &&
@@ -262,7 +263,7 @@
262
263
  <dt
263
264
  class={cn(
264
265
  "flex items-center gap-1.5 text-xs text-muted-foreground",
265
- labelPosition === "beside" && "shrink-0",
266
+ labelPosition === "beside" ? "shrink-0" : "[overflow-wrap:anywhere]",
266
267
  )}
267
268
  >
268
269
  {#if row.term}
@@ -301,7 +302,7 @@
301
302
  <h2 class="text-xs font-medium tracking-wide text-muted-foreground uppercase">{title}</h2>
302
303
  {/if}
303
304
  <dl
304
- class="grid grid-cols-[minmax(5rem,max-content)_minmax(0,1fr)] items-start gap-x-4 gap-y-2.5"
305
+ class="grid grid-cols-[minmax(5rem,min(max-content,45%))_minmax(0,1fr)] items-start gap-x-4 gap-y-2.5"
305
306
  >
306
307
  {#each shown as row, index (row.divider ? `divider-${index}` : keyOf(row))}
307
308
  {#if row.divider}
@@ -311,7 +312,7 @@
311
312
  {@const long = row.input === "longtext"}
312
313
  <dt
313
314
  class={cn(
314
- "flex min-h-7 items-center gap-2 text-sm text-muted-foreground",
315
+ "flex min-h-7 min-w-0 items-center gap-2 text-sm [overflow-wrap:anywhere] text-muted-foreground",
315
316
  long && "col-span-2 min-h-0",
316
317
  )}
317
318
  >
@@ -8,7 +8,7 @@
8
8
  import StatusBadge from "../status/status-badge.svelte";
9
9
  import { gutterClass } from "./gutter.js";
10
10
  import { formatRange } from "./format.js";
11
- import { todayIso } from "../tasks/dates.js";
11
+ import { todayIso } from "../work/dates.js";
12
12
  import { resolveLabels, type RecordLabels, type RecordNext } from "./types.js";
13
13
 
14
14
  // =========================
@@ -6,7 +6,7 @@
6
6
  import { Progress } from "../shadcn/progress/index.js";
7
7
  import { TONE_TEXT } from "../lib/tone.js";
8
8
  import StatusBadge from "../status/status-badge.svelte";
9
- import { todayIso } from "../tasks/dates.js";
9
+ import { todayIso } from "../work/dates.js";
10
10
  import { formatMoney, formatRange } from "./format.js";
11
11
  import {
12
12
  resolveLabels,
@@ -198,7 +198,7 @@
198
198
  {#snippet header()}
199
199
  <RecordHeader
200
200
  title={website.name}
201
- parent={{ label: "Marlow & Finch", href: "#client" }}
201
+ parent={{ label: "Marlow & Finch", href: "#" }}
202
202
  stage={stage ? { label: stage.label, tone: stage.tone } : null}
203
203
  facts={[
204
204
  formatMoney(website.value ?? 0, "EUR", locale),
@@ -287,7 +287,7 @@
287
287
  {#snippet header()}
288
288
  <RecordHeader
289
289
  title="Marlow & Finch"
290
- parent={{ label: "Clients", href: "#clients" }}
290
+ parent={{ label: "Clients", href: "#" }}
291
291
  facts={[
292
292
  `Pipeline ${formatMoney(rollup.totals.EUR?.pipeline ?? 0, "EUR", locale, true)}`,
293
293
  `Won ${formatMoney(rollup.totals.EUR?.won ?? 0, "EUR", locale, true)}`,
@@ -18,7 +18,7 @@
18
18
  import { Skeleton } from "../shadcn/skeleton/index.js";
19
19
  import * as Popover from "../shadcn/popover/index.js";
20
20
  import * as ContextMenu from "../shadcn/context-menu/index.js";
21
- import { todayIso } from "../tasks/dates.js";
21
+ import { todayIso } from "../work/dates.js";
22
22
  import { formatRange } from "./format.js";
23
23
  import {
24
24
  groupSteps,
@@ -280,8 +280,8 @@
280
280
  <DotsThreeVertical class="size-4" weight="bold" />
281
281
  {#if hiddenCount > 0}
282
282
  <span
283
- class="absolute -top-0.5 -right-0.5 flex size-4 items-center justify-center rounded-full bg-muted text-xs font-medium tabular-nums"
284
- >{hiddenCount}</span
283
+ class="absolute -top-0.5 -right-0.5 flex h-4 min-w-4 items-center justify-center rounded-full bg-muted px-1 text-xs font-medium tabular-nums"
284
+ >{hiddenCount.toLocaleString()}</span
285
285
  >
286
286
  {/if}
287
287
  </Button>
@@ -2,7 +2,7 @@
2
2
  import { type VariantProps, tv } from "tailwind-variants";
3
3
 
4
4
  export const badgeVariants = tv({
5
- base: "h-5 gap-1 rounded-full border border-transparent px-2 py-0.5 text-xs font-medium has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&>svg]:size-3! focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive group/badge inline-flex w-fit shrink-0 items-center justify-center overflow-hidden whitespace-nowrap transition-[background-color,border-color,color,box-shadow] focus-visible:ring-[3px] [&>svg]:pointer-events-none",
5
+ base: "h-5 gap-1 rounded-full border border-transparent px-2 py-0.5 text-xs font-medium has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&>svg]:size-3! focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive group/badge inline-flex w-fit max-w-full shrink-0 items-center justify-center overflow-hidden whitespace-nowrap transition-[background-color,border-color,color,box-shadow] focus-visible:ring-[3px] [&>svg]:pointer-events-none",
6
6
  variants: {
7
7
  // Three weights a label can carry: filled, tinted, outlined. Severity is the
8
8
  // `tone` prop, which reads `TONE_CLASS`, not a variant.
@@ -2,11 +2,7 @@
2
2
  import type { HTMLAttributes } from "svelte/elements";
3
3
  import { cn, type WithElementRef } from "../../lib/utils.js";
4
4
 
5
- // WHY: card titles render as a div by default for backwards compatibility,
6
-
7
- // but a page whose sections are all cards ends up with no headings below the h1, so screen readers cannot navigate it by heading (WCAG 2.4.6).
8
-
9
- // Pass `as="h2"` on real section titles.
5
+ // WHY: card titles default to a div, so pass `as="h2"` on real section titles or a page of cards has no headings for screen readers (WCAG 2.4.6).
10
6
  let {
11
7
  ref = $bindable(null),
12
8
  class: className,
@@ -14,7 +14,7 @@
14
14
  bind:this={ref}
15
15
  data-slot="empty-description"
16
16
  class={cn(
17
- "text-sm/relaxed text-muted-foreground [&>a:hover]:text-primary text-sm/relaxed [&>a]:underline [&>a]:underline-offset-4",
17
+ "text-sm/relaxed text-muted-foreground [overflow-wrap:anywhere] [&>a:hover]:text-primary text-sm/relaxed [&>a]:underline [&>a]:underline-offset-4",
18
18
  className,
19
19
  )}
20
20
  {...restProps}
@@ -15,6 +15,13 @@
15
15
  /** The fill's colour on the severity scale. Left out, the primary colour. */
16
16
  tone?: Tone;
17
17
  } = $props();
18
+
19
+ // WHY clamped: a value past max drew a positive translateX and the fill left its track.
20
+ let pct = $derived.by(() => {
21
+ const top = max && max > 0 ? max : 1;
22
+ const raw = (100 * (value ?? 0)) / top;
23
+ return Number.isFinite(raw) ? Math.min(100, Math.max(0, raw)) : 0;
24
+ });
18
25
  </script>
19
26
 
20
27
  <ProgressPrimitive.Root
@@ -31,6 +38,6 @@
31
38
  <div
32
39
  data-slot="progress-indicator"
33
40
  class="{progressToneClass(tone)} size-full flex-1 transition-transform duration-[var(--duration-slow)] ease-[var(--ease-smooth-out)] motion-reduce:transition-none"
34
- style="transform: translateX(-{100 - (100 * (value ?? 0)) / (max ?? 1)}%)"
41
+ style="transform: translateX(-{100 - pct}%)"
35
42
  ></div>
36
43
  </ProgressPrimitive.Root>
@@ -5,15 +5,23 @@
5
5
  let {
6
6
  ref = $bindable(null),
7
7
  class: className,
8
+ wrap = false,
8
9
  children,
9
10
  ...restProps
10
- }: WithElementRef<HTMLTdAttributes> = $props();
11
+ }: WithElementRef<HTMLTdAttributes> & {
12
+ /** Lets a long user string wrap, so a trailing action cell keeps its place. Off by default: amounts and dates stay on one line. */
13
+ wrap?: boolean;
14
+ } = $props();
11
15
  </script>
12
16
 
13
17
  <td
14
18
  bind:this={ref}
15
19
  data-slot="table-cell"
16
- class={cn("p-2 align-middle whitespace-nowrap tabular-nums [&:has([role=checkbox])]:pr-0", className)}
20
+ class={cn(
21
+ "p-2 align-middle tabular-nums [&:has([role=checkbox])]:pr-0",
22
+ wrap ? "whitespace-normal [overflow-wrap:anywhere]" : "whitespace-nowrap",
23
+ className,
24
+ )}
17
25
  {...restProps}
18
26
  >
19
27
  {@render children?.()}
@@ -1,6 +1,6 @@
1
1
  # @heyramzi/ui/status
2
2
 
3
- Status badge, dot and icon from one map. `defineStatuses` builds the map, and the three parts read it, so a status looks the same everywhere. They used to live in `@heyramzi/ui/tasks`, which still re-exports every name.
3
+ Status badge, dot and icon from one map. `defineStatuses` builds the map, and the three parts read it, so a status looks the same everywhere. They used to live in `@heyramzi/ui/work`, which still re-exports every name.
4
4
 
5
5
  ```svelte
6
6
  <script lang="ts">
@@ -24,6 +24,8 @@ One comment thread for any subject: a task, a project, a doc or a diagram. The t
24
24
  - **Resolve.** Pass `onResolve` and each root gets a check. Resolved roots fold away behind a "Show N resolved" button.
25
25
  - **Anchor.** `anchor` carries `{ nodeId, dx, dy, x, y }` for a canvas pin. A pinned comment shows a chip, and `onAnchor` fires on a click so the canvas can move to the node. `anchorChip` replaces the chip.
26
26
  - **Attachments.** The `attachments` snippet draws under a comment's body.
27
+ - **Events.** `events` takes `ThreadEvent`s (a whole sentence, a time, an optional Phosphor icon) and draws each as one `Trace` line between the conversations, in time order. `whenEvent(event)` formats its time. `interleave(nodes, events)` gives the same order without the component.
28
+ - **Long bodies.** A body over 6 lines folds behind `showMore` and `showLess`.
27
29
  - **Labels.** Every string comes from `labels`, a partial of `ThreadLabels`. `showResolved` holds a `{count}` slot. `when(comment)` formats the time.
28
30
 
29
31
  ```ts
@@ -1,11 +1,19 @@
1
1
  export { default as Thread } from "./thread.svelte";
2
- export { buildThread, fillCount, resolveThreadLabels, resolvedCount } from "./logic.js";
2
+ export {
3
+ buildThread,
4
+ fillCount,
5
+ interleave,
6
+ resolveThreadLabels,
7
+ resolvedCount,
8
+ } from "./logic.js";
3
9
  export { DEFAULT_THREAD_LABELS } from "./types.js";
4
10
  export type {
5
11
  ThreadAnchor,
6
12
  ThreadAuthor,
7
13
  ThreadAuthorKind,
8
14
  ThreadComment,
15
+ ThreadEvent,
16
+ ThreadItem,
9
17
  ThreadLabels,
10
18
  ThreadNode,
11
19
  ThreadPost,
@@ -1,11 +1,22 @@
1
- import type { ThreadComment, ThreadLabels, ThreadNode } from "./types.js";
1
+ import type {
2
+ ThreadComment,
3
+ ThreadEvent,
4
+ ThreadItem,
5
+ ThreadLabels,
6
+ ThreadNode,
7
+ } from "./types.js";
2
8
  import { DEFAULT_THREAD_LABELS } from "./types.js";
3
9
 
4
- function time(comment: ThreadComment): number {
5
- const ms = Date.parse(comment.createdAt);
10
+ /** A timestamp as a number, a malformed one last. */
11
+ function at(iso: string): number {
12
+ const ms = Date.parse(iso);
6
13
  return Number.isNaN(ms) ? Number.POSITIVE_INFINITY : ms;
7
14
  }
8
15
 
16
+ function time(comment: ThreadComment): number {
17
+ return at(comment.createdAt);
18
+ }
19
+
9
20
  /** Oldest first, a malformed timestamp last, ties in the order they came. */
10
21
  function byTime(comments: ThreadComment[]): ThreadComment[] {
11
22
  return comments
@@ -59,3 +70,22 @@ export function resolveThreadLabels(overrides?: Partial<ThreadLabels>): ThreadLa
59
70
  export function fillCount(label: string, count: number): string {
60
71
  return label.replaceAll("{count}", String(count));
61
72
  }
73
+
74
+ /** Conversations and events in time order, each run of events between two conversations as one item. */
75
+ export function interleave(nodes: ThreadNode[], events: ThreadEvent[]): ThreadItem[] {
76
+ const timed = [
77
+ ...nodes.map((node, index) => ({ at: at(node.comment.createdAt), index, node })),
78
+ ...events.map((event, index) => ({ at: at(event.at), index: nodes.length + index, event })),
79
+ ].toSorted((a, b) => a.at - b.at || a.index - b.index);
80
+ const items: ThreadItem[] = [];
81
+ for (const row of timed) {
82
+ if ("node" in row) {
83
+ items.push({ type: "node", key: row.node.comment.id, node: row.node });
84
+ continue;
85
+ }
86
+ const last = items.at(-1);
87
+ if (last?.type === "events") last.events.push(row.event);
88
+ else items.push({ type: "events", key: row.event.id, events: [row.event] });
89
+ }
90
+ return items;
91
+ }
@@ -0,0 +1,37 @@
1
+ <script lang="ts">
2
+ import { cn } from "../lib/utils.js";
3
+
4
+ interface Props {
5
+ text: string;
6
+ more: string;
7
+ less: string;
8
+ class?: string;
9
+ }
10
+
11
+ let { text, more, less, class: className }: Props = $props();
12
+
13
+ let open = $state(false);
14
+ let long = $derived(text.length > 420 || text.split("\n").length > 6);
15
+ </script>
16
+
17
+ <div class="flex flex-col items-start gap-1">
18
+ <p
19
+ class={cn(
20
+ "text-sm leading-relaxed font-normal whitespace-pre-wrap text-pretty",
21
+ long && !open && "line-clamp-6",
22
+ className,
23
+ )}
24
+ >
25
+ {text}
26
+ </p>
27
+ {#if long}
28
+ <button
29
+ type="button"
30
+ class="text-muted-foreground hover:text-foreground text-xs underline-offset-2 hover:underline"
31
+ aria-expanded={open}
32
+ onclick={() => (open = !open)}
33
+ >
34
+ {open ? less : more}
35
+ </button>
36
+ {/if}
37
+ </div>
@@ -0,0 +1,30 @@
1
+ <script lang="ts">
2
+ import * as TraceUI from "../shadcn/trace/index.js";
3
+ import type { ThreadEvent } from "./types.js";
4
+
5
+ interface Props {
6
+ events: ThreadEvent[];
7
+ when: (event: ThreadEvent) => string;
8
+ }
9
+
10
+ let { events, when }: Props = $props();
11
+ </script>
12
+
13
+ <!-- ps-1 centres each 16px icon in the 24px avatar column the comments use. -->
14
+ <TraceUI.Trace class="gap-1 ps-1">
15
+ {#each events as event (event.id)}
16
+ {@const Icon = event.icon}
17
+ <TraceUI.Line class="w-full items-start text-xs">
18
+ {#if Icon}
19
+ <TraceUI.Icon class="mt-px"><Icon size={14} /></TraceUI.Icon>
20
+ {/if}
21
+ <!-- Wraps, not truncates: a status name can be a sentence, and a touch screen has no hover title. -->
22
+ <TraceUI.Title class="flex-1 whitespace-normal text-pretty [overflow-wrap:anywhere]"
23
+ >{event.title}</TraceUI.Title
24
+ >
25
+ <TraceUI.Description>
26
+ <time datetime={event.at}>{when(event)}</time>
27
+ </TraceUI.Description>
28
+ </TraceUI.Line>
29
+ {/each}
30
+ </TraceUI.Trace>