@workflow/web-shared 5.0.0-beta.4 → 5.0.0-beta.41

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 (517) hide show
  1. package/README.md +5 -13
  2. package/dist/components/error-boundary.js +1 -1
  3. package/dist/components/event-list-view.d.ts +46 -1
  4. package/dist/components/event-list-view.d.ts.map +1 -1
  5. package/dist/components/event-list-view.js +235 -97
  6. package/dist/components/hook-actions.js +1 -1
  7. package/dist/components/index.d.ts +8 -5
  8. package/dist/components/index.d.ts.map +1 -1
  9. package/dist/components/index.js +6 -4
  10. package/dist/components/sidebar/attribute-panel.d.ts +4 -1
  11. package/dist/components/sidebar/attribute-panel.d.ts.map +1 -1
  12. package/dist/components/sidebar/attribute-panel.js +173 -119
  13. package/dist/components/sidebar/attributes-block.d.ts +40 -0
  14. package/dist/components/sidebar/attributes-block.d.ts.map +1 -0
  15. package/dist/components/sidebar/attributes-block.js +140 -0
  16. package/dist/components/sidebar/conversation-view.js +1 -1
  17. package/dist/components/sidebar/copyable-data-block.d.ts +2 -0
  18. package/dist/components/sidebar/copyable-data-block.d.ts.map +1 -1
  19. package/dist/components/sidebar/copyable-data-block.js +17 -16
  20. package/dist/components/sidebar/entity-detail-panel.d.ts +11 -11
  21. package/dist/components/sidebar/entity-detail-panel.d.ts.map +1 -1
  22. package/dist/components/sidebar/entity-detail-panel.js +37 -71
  23. package/dist/components/sidebar/events-list.d.ts +6 -2
  24. package/dist/components/sidebar/events-list.d.ts.map +1 -1
  25. package/dist/components/sidebar/events-list.js +77 -63
  26. package/dist/components/sidebar/resolve-hook-modal.js +1 -1
  27. package/dist/components/sidebar/sidebar-data-context.d.ts +10 -7
  28. package/dist/components/sidebar/sidebar-data-context.d.ts.map +1 -1
  29. package/dist/components/sidebar/sidebar-data-context.js +1 -1
  30. package/dist/components/sidebar/span-detail-merge.d.ts +31 -0
  31. package/dist/components/sidebar/span-detail-merge.d.ts.map +1 -0
  32. package/dist/components/sidebar/span-detail-merge.js +92 -0
  33. package/dist/components/sidebar/use-selected-span-detail.d.ts +16 -0
  34. package/dist/components/sidebar/use-selected-span-detail.d.ts.map +1 -0
  35. package/dist/components/sidebar/use-selected-span-detail.js +93 -0
  36. package/dist/components/stream-viewer-skeleton.d.ts +2 -0
  37. package/dist/components/stream-viewer-skeleton.d.ts.map +1 -0
  38. package/dist/components/stream-viewer-skeleton.js +12 -0
  39. package/dist/components/stream-viewer.d.ts +1 -1
  40. package/dist/components/stream-viewer.d.ts.map +1 -1
  41. package/dist/components/stream-viewer.js +9 -26
  42. package/dist/components/trace-viewer/components/copy-button.d.ts.map +1 -0
  43. package/dist/components/trace-viewer/components/copy-button.js +27 -0
  44. package/dist/components/trace-viewer/components/detail-panel-width.d.ts +34 -0
  45. package/dist/components/trace-viewer/components/detail-panel-width.d.ts.map +1 -0
  46. package/dist/components/trace-viewer/components/detail-panel-width.js +67 -0
  47. package/dist/components/trace-viewer/components/detail-panel.d.ts +14 -0
  48. package/dist/components/trace-viewer/components/detail-panel.d.ts.map +1 -0
  49. package/dist/components/trace-viewer/components/detail-panel.js +122 -0
  50. package/dist/components/trace-viewer/components/draggable-border.d.ts +31 -0
  51. package/dist/components/trace-viewer/components/draggable-border.d.ts.map +1 -0
  52. package/dist/components/trace-viewer/components/draggable-border.js +140 -0
  53. package/dist/components/trace-viewer/components/event-list.d.ts +10 -0
  54. package/dist/components/trace-viewer/components/event-list.d.ts.map +1 -0
  55. package/dist/components/trace-viewer/components/event-list.js +47 -0
  56. package/dist/components/trace-viewer/components/middle-truncate/copy-selection.d.ts.map +1 -0
  57. package/dist/components/trace-viewer/components/middle-truncate/copy-selection.js +54 -0
  58. package/dist/components/trace-viewer/components/middle-truncate/middle-truncate.d.ts.map +1 -0
  59. package/dist/components/trace-viewer/components/middle-truncate/middle-truncate.js +81 -0
  60. package/dist/components/{new-trace-viewer → trace-viewer}/components/middle-truncate/truncate.d.ts +1 -1
  61. package/dist/components/trace-viewer/components/middle-truncate/truncate.d.ts.map +1 -0
  62. package/dist/components/trace-viewer/components/middle-truncate/truncate.js +101 -0
  63. package/dist/components/trace-viewer/components/middle-truncate/use-middle-truncate.d.ts.map +1 -0
  64. package/dist/components/trace-viewer/components/middle-truncate/use-middle-truncate.js +114 -0
  65. package/dist/components/trace-viewer/components/minimap.d.ts +14 -0
  66. package/dist/components/trace-viewer/components/minimap.d.ts.map +1 -0
  67. package/dist/components/trace-viewer/components/minimap.js +337 -0
  68. package/dist/components/trace-viewer/components/pane-constants.d.ts +14 -0
  69. package/dist/components/trace-viewer/components/pane-constants.d.ts.map +1 -0
  70. package/dist/components/trace-viewer/components/pane-constants.js +16 -0
  71. package/dist/components/trace-viewer/components/span-markers.d.ts +46 -0
  72. package/dist/components/trace-viewer/components/span-markers.d.ts.map +1 -0
  73. package/dist/components/trace-viewer/components/span-markers.js +85 -0
  74. package/dist/components/trace-viewer/components/split-pane.d.ts +10 -0
  75. package/dist/components/trace-viewer/components/split-pane.d.ts.map +1 -0
  76. package/dist/components/trace-viewer/components/split-pane.js +41 -0
  77. package/dist/components/trace-viewer/components/timeline.d.ts +42 -0
  78. package/dist/components/trace-viewer/components/timeline.d.ts.map +1 -0
  79. package/dist/components/trace-viewer/components/timeline.js +321 -0
  80. package/dist/components/trace-viewer/components/timeline.module.css +46 -0
  81. package/dist/components/trace-viewer/components/trace-shortcut-helper.d.ts +5 -0
  82. package/dist/components/trace-viewer/components/trace-shortcut-helper.d.ts.map +1 -0
  83. package/dist/components/trace-viewer/components/trace-shortcut-helper.js +55 -0
  84. package/dist/components/trace-viewer/components/trace-shortcut-helper.module.css +20 -0
  85. package/dist/components/trace-viewer/components/trace-viewer-skeleton.d.ts +2 -0
  86. package/dist/components/trace-viewer/components/trace-viewer-skeleton.d.ts.map +1 -0
  87. package/dist/components/trace-viewer/components/trace-viewer-skeleton.js +26 -0
  88. package/dist/components/trace-viewer/components/use-element-width.d.ts +8 -0
  89. package/dist/components/trace-viewer/components/use-element-width.d.ts.map +1 -0
  90. package/dist/components/trace-viewer/components/use-element-width.js +25 -0
  91. package/dist/components/trace-viewer/components/use-row-window.d.ts +34 -0
  92. package/dist/components/trace-viewer/components/use-row-window.d.ts.map +1 -0
  93. package/dist/components/trace-viewer/components/use-row-window.js +107 -0
  94. package/dist/components/trace-viewer/context.d.ts +14 -182
  95. package/dist/components/trace-viewer/context.d.ts.map +1 -1
  96. package/dist/components/trace-viewer/context.js +44 -351
  97. package/dist/components/trace-viewer/icons.d.ts.map +1 -0
  98. package/dist/components/trace-viewer/icons.js +15 -0
  99. package/dist/components/trace-viewer/search.d.ts +19 -0
  100. package/dist/components/trace-viewer/search.d.ts.map +1 -0
  101. package/dist/components/trace-viewer/search.js +134 -0
  102. package/dist/components/trace-viewer/trace-viewer.d.ts +7 -28
  103. package/dist/components/trace-viewer/trace-viewer.d.ts.map +1 -1
  104. package/dist/components/trace-viewer/trace-viewer.js +306 -356
  105. package/dist/components/trace-viewer/types.d.ts +2 -211
  106. package/dist/components/trace-viewer/types.d.ts.map +1 -1
  107. package/dist/components/trace-viewer/types.js +1 -1
  108. package/dist/components/trace-viewer/util/timing.d.ts +2 -2
  109. package/dist/components/trace-viewer/util/timing.d.ts.map +1 -1
  110. package/dist/components/trace-viewer/util/timing.js +3 -3
  111. package/dist/components/trace-viewer/utils.d.ts +111 -0
  112. package/dist/components/trace-viewer/utils.d.ts.map +1 -0
  113. package/dist/components/trace-viewer/utils.js +430 -0
  114. package/dist/components/{trace-viewer-new.d.ts → trace-viewer.d.ts} +7 -3
  115. package/dist/components/trace-viewer.d.ts.map +1 -0
  116. package/dist/components/trace-viewer.js +21 -0
  117. package/dist/components/ui/alert.js +3 -3
  118. package/dist/components/ui/button.d.ts +10 -0
  119. package/dist/components/ui/button.d.ts.map +1 -0
  120. package/dist/components/ui/button.js +46 -0
  121. package/dist/components/ui/card.d.ts.map +1 -1
  122. package/dist/components/ui/card.js +4 -4
  123. package/dist/components/ui/collapsible.d.ts +46 -0
  124. package/dist/components/ui/collapsible.d.ts.map +1 -0
  125. package/dist/components/ui/collapsible.js +66 -0
  126. package/dist/components/ui/context-card.d.ts +47 -0
  127. package/dist/components/ui/context-card.d.ts.map +1 -0
  128. package/dist/components/ui/context-card.js +471 -0
  129. package/dist/components/ui/data-inspector.d.ts +7 -6
  130. package/dist/components/ui/data-inspector.d.ts.map +1 -1
  131. package/dist/components/ui/data-inspector.js +232 -99
  132. package/dist/components/ui/data-inspector.styles.d.ts +29 -0
  133. package/dist/components/ui/data-inspector.styles.d.ts.map +1 -0
  134. package/dist/components/ui/data-inspector.styles.js +95 -0
  135. package/dist/components/ui/decrypt-button.js +1 -1
  136. package/dist/components/ui/error-card.js +3 -3
  137. package/dist/components/ui/error-stack-block.d.ts +17 -10
  138. package/dist/components/ui/error-stack-block.d.ts.map +1 -1
  139. package/dist/components/ui/error-stack-block.js +49 -30
  140. package/dist/components/ui/icon-button.d.ts +19 -0
  141. package/dist/components/ui/icon-button.d.ts.map +1 -0
  142. package/dist/components/ui/icon-button.js +29 -0
  143. package/dist/components/ui/kbd.d.ts +10 -0
  144. package/dist/components/ui/kbd.d.ts.map +1 -0
  145. package/dist/components/ui/kbd.js +25 -0
  146. package/dist/components/ui/load-more-button.js +1 -1
  147. package/dist/components/ui/menu-dropdown.js +1 -1
  148. package/dist/components/ui/skeleton.js +2 -2
  149. package/dist/components/ui/spinner.js +1 -1
  150. package/dist/components/ui/timestamp-tooltip.d.ts +34 -1
  151. package/dist/components/ui/timestamp-tooltip.d.ts.map +1 -1
  152. package/dist/components/ui/timestamp-tooltip.js +80 -132
  153. package/dist/components/ui/tooltip.d.ts +10 -0
  154. package/dist/components/ui/tooltip.d.ts.map +1 -0
  155. package/dist/components/ui/tooltip.js +12 -0
  156. package/dist/components/workflow-traces/event-colors.d.ts +2 -1
  157. package/dist/components/workflow-traces/event-colors.d.ts.map +1 -1
  158. package/dist/components/workflow-traces/event-colors.js +15 -7
  159. package/dist/components/workflow-traces/trace-span-construction.d.ts +6 -3
  160. package/dist/components/workflow-traces/trace-span-construction.d.ts.map +1 -1
  161. package/dist/components/workflow-traces/trace-span-construction.js +71 -30
  162. package/dist/components/workflow-traces/trace-time-utils.js +1 -1
  163. package/dist/hooks/use-dark-mode.js +1 -1
  164. package/dist/hooks/use-intersection-observer.d.ts +17 -0
  165. package/dist/hooks/use-intersection-observer.d.ts.map +1 -0
  166. package/dist/hooks/use-intersection-observer.js +29 -0
  167. package/dist/hooks/use-load-more-on-scroll.d.ts +21 -0
  168. package/dist/hooks/use-load-more-on-scroll.d.ts.map +1 -0
  169. package/dist/hooks/use-load-more-on-scroll.js +28 -0
  170. package/dist/hooks/use-reduced-motion.d.ts +10 -0
  171. package/dist/hooks/use-reduced-motion.d.ts.map +1 -0
  172. package/dist/hooks/use-reduced-motion.js +29 -0
  173. package/dist/index.d.ts +4 -3
  174. package/dist/index.d.ts.map +1 -1
  175. package/dist/index.js +4 -3
  176. package/dist/lib/cn.d.ts +10 -0
  177. package/dist/lib/cn.d.ts.map +1 -0
  178. package/dist/lib/cn.js +83 -0
  179. package/dist/lib/event-analysis.d.ts +1 -1
  180. package/dist/lib/event-analysis.d.ts.map +1 -1
  181. package/dist/lib/event-analysis.js +3 -2
  182. package/dist/lib/event-materialization.d.ts +1 -1
  183. package/dist/lib/event-materialization.d.ts.map +1 -1
  184. package/dist/lib/event-materialization.js +29 -21
  185. package/dist/lib/exact-event-search-id.d.ts +25 -0
  186. package/dist/lib/exact-event-search-id.d.ts.map +1 -0
  187. package/dist/lib/exact-event-search-id.js +39 -0
  188. package/dist/lib/hydration.d.ts +17 -2
  189. package/dist/lib/hydration.d.ts.map +1 -1
  190. package/dist/lib/hydration.js +194 -23
  191. package/dist/lib/stream-display.js +1 -1
  192. package/dist/lib/toast.js +1 -1
  193. package/dist/lib/trace-builder.d.ts +17 -5
  194. package/dist/lib/trace-builder.d.ts.map +1 -1
  195. package/dist/lib/trace-builder.js +32 -14
  196. package/dist/lib/trace-types.d.ts +54 -0
  197. package/dist/lib/trace-types.d.ts.map +1 -0
  198. package/dist/lib/trace-types.js +2 -0
  199. package/dist/lib/utils.d.ts +14 -2
  200. package/dist/lib/utils.d.ts.map +1 -1
  201. package/dist/lib/utils.js +46 -6
  202. package/dist/lib/zstd-browser-decoder.d.ts +7 -0
  203. package/dist/lib/zstd-browser-decoder.d.ts.map +1 -0
  204. package/dist/lib/zstd-browser-decoder.js +41 -0
  205. package/dist/styles.css +210 -139
  206. package/package.json +11 -8
  207. package/src/components/event-list-view.tsx +385 -123
  208. package/src/components/index.ts +14 -8
  209. package/src/components/sidebar/attribute-panel.tsx +331 -282
  210. package/src/components/sidebar/attributes-block.tsx +326 -0
  211. package/src/components/sidebar/copyable-data-block.tsx +50 -28
  212. package/src/components/sidebar/entity-detail-panel.tsx +92 -126
  213. package/src/components/sidebar/events-list.tsx +197 -179
  214. package/src/components/sidebar/sidebar-data-context.tsx +11 -11
  215. package/src/components/sidebar/span-detail-merge.ts +134 -0
  216. package/src/components/sidebar/use-selected-span-detail.ts +146 -0
  217. package/src/components/stream-viewer-skeleton.tsx +34 -0
  218. package/src/components/stream-viewer.tsx +34 -106
  219. package/src/components/{new-trace-viewer → trace-viewer}/components/copy-button.tsx +2 -2
  220. package/src/components/trace-viewer/components/detail-panel-width.test.ts +123 -0
  221. package/src/components/trace-viewer/components/detail-panel-width.ts +76 -0
  222. package/src/components/trace-viewer/components/detail-panel.tsx +273 -0
  223. package/src/components/trace-viewer/components/draggable-border.tsx +216 -0
  224. package/src/components/trace-viewer/components/event-list.tsx +144 -0
  225. package/src/components/{new-trace-viewer → trace-viewer}/components/middle-truncate/middle-truncate.tsx +8 -8
  226. package/src/components/{new-trace-viewer → trace-viewer}/components/middle-truncate/truncate.ts +1 -1
  227. package/src/components/trace-viewer/components/minimap.tsx +556 -0
  228. package/src/components/trace-viewer/components/pane-constants.ts +19 -0
  229. package/src/components/trace-viewer/components/span-markers.tsx +173 -0
  230. package/src/components/trace-viewer/components/split-pane.tsx +141 -0
  231. package/src/components/trace-viewer/components/timeline.module.css +46 -0
  232. package/src/components/trace-viewer/components/timeline.tsx +850 -0
  233. package/src/components/trace-viewer/components/trace-shortcut-helper.module.css +20 -0
  234. package/src/components/trace-viewer/components/trace-shortcut-helper.tsx +116 -0
  235. package/src/components/trace-viewer/components/trace-viewer-skeleton.tsx +114 -0
  236. package/src/components/trace-viewer/components/use-element-width.ts +29 -0
  237. package/src/components/trace-viewer/components/use-row-window.ts +140 -0
  238. package/src/components/trace-viewer/context.tsx +63 -656
  239. package/src/components/{new-trace-viewer → trace-viewer}/icons.tsx +2 -2
  240. package/src/components/trace-viewer/search.ts +178 -0
  241. package/src/components/trace-viewer/trace-viewer.tsx +563 -531
  242. package/src/components/trace-viewer/types.ts +2 -234
  243. package/src/components/trace-viewer/util/timing.ts +2 -2
  244. package/src/components/trace-viewer/utils.test.ts +458 -0
  245. package/src/components/{new-trace-viewer → trace-viewer}/utils.ts +271 -50
  246. package/src/components/{trace-viewer-new.tsx → trace-viewer.tsx} +24 -18
  247. package/src/components/ui/alert.tsx +2 -2
  248. package/src/components/ui/button.tsx +68 -0
  249. package/src/components/ui/card.tsx +3 -10
  250. package/src/components/ui/collapsible.tsx +219 -0
  251. package/src/components/ui/context-card.tsx +784 -0
  252. package/src/components/ui/data-inspector.styles.ts +96 -0
  253. package/src/components/ui/data-inspector.tsx +501 -204
  254. package/src/components/ui/error-card.tsx +4 -4
  255. package/src/components/ui/error-stack-block.tsx +84 -55
  256. package/src/components/ui/icon-button.tsx +53 -0
  257. package/src/components/ui/kbd.tsx +43 -0
  258. package/src/components/ui/skeleton.tsx +1 -1
  259. package/src/components/ui/timestamp-tooltip.tsx +132 -194
  260. package/src/components/ui/tooltip.tsx +47 -0
  261. package/src/components/workflow-traces/event-colors.ts +15 -11
  262. package/src/components/workflow-traces/trace-span-construction.test.ts +85 -0
  263. package/src/components/workflow-traces/trace-span-construction.ts +97 -32
  264. package/src/hooks/use-intersection-observer.ts +57 -0
  265. package/src/hooks/use-load-more-on-scroll.ts +49 -0
  266. package/src/hooks/use-reduced-motion.ts +34 -0
  267. package/src/index.ts +10 -4
  268. package/src/lib/cn.ts +93 -0
  269. package/src/lib/event-analysis.ts +6 -4
  270. package/src/lib/event-materialization.ts +35 -21
  271. package/src/lib/exact-event-search-id.ts +67 -0
  272. package/src/lib/hydration.ts +210 -30
  273. package/src/lib/trace-builder.ts +43 -19
  274. package/src/lib/trace-types.ts +56 -0
  275. package/src/lib/utils.test.ts +33 -0
  276. package/src/lib/utils.ts +53 -6
  277. package/src/lib/zstd-browser-decoder.ts +42 -0
  278. package/src/styles.css +210 -139
  279. package/dist/components/error-boundary.js.map +0 -1
  280. package/dist/components/event-list-view.js.map +0 -1
  281. package/dist/components/hook-actions.js.map +0 -1
  282. package/dist/components/index.js.map +0 -1
  283. package/dist/components/new-trace-viewer/components/copy-button.d.ts.map +0 -1
  284. package/dist/components/new-trace-viewer/components/copy-button.js +0 -27
  285. package/dist/components/new-trace-viewer/components/copy-button.js.map +0 -1
  286. package/dist/components/new-trace-viewer/components/event-list.d.ts +0 -8
  287. package/dist/components/new-trace-viewer/components/event-list.d.ts.map +0 -1
  288. package/dist/components/new-trace-viewer/components/event-list.js +0 -38
  289. package/dist/components/new-trace-viewer/components/event-list.js.map +0 -1
  290. package/dist/components/new-trace-viewer/components/middle-truncate/copy-selection.d.ts.map +0 -1
  291. package/dist/components/new-trace-viewer/components/middle-truncate/copy-selection.js +0 -54
  292. package/dist/components/new-trace-viewer/components/middle-truncate/copy-selection.js.map +0 -1
  293. package/dist/components/new-trace-viewer/components/middle-truncate/middle-truncate.d.ts.map +0 -1
  294. package/dist/components/new-trace-viewer/components/middle-truncate/middle-truncate.js +0 -81
  295. package/dist/components/new-trace-viewer/components/middle-truncate/middle-truncate.js.map +0 -1
  296. package/dist/components/new-trace-viewer/components/middle-truncate/truncate.d.ts.map +0 -1
  297. package/dist/components/new-trace-viewer/components/middle-truncate/truncate.js +0 -101
  298. package/dist/components/new-trace-viewer/components/middle-truncate/truncate.js.map +0 -1
  299. package/dist/components/new-trace-viewer/components/middle-truncate/use-middle-truncate.d.ts.map +0 -1
  300. package/dist/components/new-trace-viewer/components/middle-truncate/use-middle-truncate.js +0 -114
  301. package/dist/components/new-trace-viewer/components/middle-truncate/use-middle-truncate.js.map +0 -1
  302. package/dist/components/new-trace-viewer/components/split-pane.d.ts +0 -14
  303. package/dist/components/new-trace-viewer/components/split-pane.d.ts.map +0 -1
  304. package/dist/components/new-trace-viewer/components/split-pane.js +0 -99
  305. package/dist/components/new-trace-viewer/components/split-pane.js.map +0 -1
  306. package/dist/components/new-trace-viewer/components/timeline.d.ts +0 -31
  307. package/dist/components/new-trace-viewer/components/timeline.d.ts.map +0 -1
  308. package/dist/components/new-trace-viewer/components/timeline.js +0 -138
  309. package/dist/components/new-trace-viewer/components/timeline.js.map +0 -1
  310. package/dist/components/new-trace-viewer/context.d.ts +0 -15
  311. package/dist/components/new-trace-viewer/context.d.ts.map +0 -1
  312. package/dist/components/new-trace-viewer/context.js +0 -47
  313. package/dist/components/new-trace-viewer/context.js.map +0 -1
  314. package/dist/components/new-trace-viewer/detail-panel.d.ts +0 -10
  315. package/dist/components/new-trace-viewer/detail-panel.d.ts.map +0 -1
  316. package/dist/components/new-trace-viewer/detail-panel.js +0 -12
  317. package/dist/components/new-trace-viewer/detail-panel.js.map +0 -1
  318. package/dist/components/new-trace-viewer/icons.d.ts.map +0 -1
  319. package/dist/components/new-trace-viewer/icons.js +0 -15
  320. package/dist/components/new-trace-viewer/icons.js.map +0 -1
  321. package/dist/components/new-trace-viewer/trace-viewer.d.ts +0 -8
  322. package/dist/components/new-trace-viewer/trace-viewer.d.ts.map +0 -1
  323. package/dist/components/new-trace-viewer/trace-viewer.js +0 -349
  324. package/dist/components/new-trace-viewer/trace-viewer.js.map +0 -1
  325. package/dist/components/new-trace-viewer/types.d.ts +0 -1
  326. package/dist/components/new-trace-viewer/types.d.ts.map +0 -1
  327. package/dist/components/new-trace-viewer/types.js +0 -2
  328. package/dist/components/new-trace-viewer/types.js.map +0 -1
  329. package/dist/components/new-trace-viewer/util/constants.d.ts +0 -1
  330. package/dist/components/new-trace-viewer/util/constants.d.ts.map +0 -1
  331. package/dist/components/new-trace-viewer/util/constants.js +0 -2
  332. package/dist/components/new-trace-viewer/util/constants.js.map +0 -1
  333. package/dist/components/new-trace-viewer/utils.d.ts +0 -42
  334. package/dist/components/new-trace-viewer/utils.d.ts.map +0 -1
  335. package/dist/components/new-trace-viewer/utils.js +0 -305
  336. package/dist/components/new-trace-viewer/utils.js.map +0 -1
  337. package/dist/components/run-trace-view.d.ts +0 -25
  338. package/dist/components/run-trace-view.d.ts.map +0 -1
  339. package/dist/components/run-trace-view.js +0 -11
  340. package/dist/components/run-trace-view.js.map +0 -1
  341. package/dist/components/sidebar/attribute-panel.js.map +0 -1
  342. package/dist/components/sidebar/conversation-view.js.map +0 -1
  343. package/dist/components/sidebar/copyable-data-block.js.map +0 -1
  344. package/dist/components/sidebar/detail-card.d.ts +0 -14
  345. package/dist/components/sidebar/detail-card.d.ts.map +0 -1
  346. package/dist/components/sidebar/detail-card.js +0 -20
  347. package/dist/components/sidebar/detail-card.js.map +0 -1
  348. package/dist/components/sidebar/entity-detail-panel.js.map +0 -1
  349. package/dist/components/sidebar/events-list.js.map +0 -1
  350. package/dist/components/sidebar/resolve-hook-modal.js.map +0 -1
  351. package/dist/components/sidebar/sidebar-data-context.js.map +0 -1
  352. package/dist/components/stream-viewer.js.map +0 -1
  353. package/dist/components/trace-viewer/components/map.d.ts +0 -8
  354. package/dist/components/trace-viewer/components/map.d.ts.map +0 -1
  355. package/dist/components/trace-viewer/components/map.js +0 -162
  356. package/dist/components/trace-viewer/components/map.js.map +0 -1
  357. package/dist/components/trace-viewer/components/markers.d.ts +0 -23
  358. package/dist/components/trace-viewer/components/markers.d.ts.map +0 -1
  359. package/dist/components/trace-viewer/components/markers.js +0 -416
  360. package/dist/components/trace-viewer/components/markers.js.map +0 -1
  361. package/dist/components/trace-viewer/components/node.d.ts +0 -35
  362. package/dist/components/trace-viewer/components/node.d.ts.map +0 -1
  363. package/dist/components/trace-viewer/components/node.js +0 -285
  364. package/dist/components/trace-viewer/components/node.js.map +0 -1
  365. package/dist/components/trace-viewer/components/search-input.d.ts +0 -9
  366. package/dist/components/trace-viewer/components/search-input.d.ts.map +0 -1
  367. package/dist/components/trace-viewer/components/search-input.js +0 -9
  368. package/dist/components/trace-viewer/components/search-input.js.map +0 -1
  369. package/dist/components/trace-viewer/components/search.d.ts +0 -3
  370. package/dist/components/trace-viewer/components/search.d.ts.map +0 -1
  371. package/dist/components/trace-viewer/components/search.js +0 -25
  372. package/dist/components/trace-viewer/components/search.js.map +0 -1
  373. package/dist/components/trace-viewer/components/span-content.d.ts +0 -19
  374. package/dist/components/trace-viewer/components/span-content.d.ts.map +0 -1
  375. package/dist/components/trace-viewer/components/span-content.js +0 -137
  376. package/dist/components/trace-viewer/components/span-content.js.map +0 -1
  377. package/dist/components/trace-viewer/components/span-detail-panel.d.ts +0 -10
  378. package/dist/components/trace-viewer/components/span-detail-panel.d.ts.map +0 -1
  379. package/dist/components/trace-viewer/components/span-detail-panel.js +0 -285
  380. package/dist/components/trace-viewer/components/span-detail-panel.js.map +0 -1
  381. package/dist/components/trace-viewer/components/span-segments.d.ts +0 -50
  382. package/dist/components/trace-viewer/components/span-segments.d.ts.map +0 -1
  383. package/dist/components/trace-viewer/components/span-segments.js +0 -445
  384. package/dist/components/trace-viewer/components/span-segments.js.map +0 -1
  385. package/dist/components/trace-viewer/components/span-strategies.d.ts +0 -46
  386. package/dist/components/trace-viewer/components/span-strategies.d.ts.map +0 -1
  387. package/dist/components/trace-viewer/components/span-strategies.js +0 -108
  388. package/dist/components/trace-viewer/components/span-strategies.js.map +0 -1
  389. package/dist/components/trace-viewer/components/ui.d.ts +0 -28
  390. package/dist/components/trace-viewer/components/ui.d.ts.map +0 -1
  391. package/dist/components/trace-viewer/components/ui.js +0 -39
  392. package/dist/components/trace-viewer/components/ui.js.map +0 -1
  393. package/dist/components/trace-viewer/components/zoom-button.d.ts +0 -3
  394. package/dist/components/trace-viewer/components/zoom-button.d.ts.map +0 -1
  395. package/dist/components/trace-viewer/components/zoom-button.js +0 -29
  396. package/dist/components/trace-viewer/components/zoom-button.js.map +0 -1
  397. package/dist/components/trace-viewer/components/zoom-icons.d.ts +0 -11
  398. package/dist/components/trace-viewer/components/zoom-icons.d.ts.map +0 -1
  399. package/dist/components/trace-viewer/components/zoom-icons.js +0 -11
  400. package/dist/components/trace-viewer/components/zoom-icons.js.map +0 -1
  401. package/dist/components/trace-viewer/context.js.map +0 -1
  402. package/dist/components/trace-viewer/index.d.ts +0 -5
  403. package/dist/components/trace-viewer/index.d.ts.map +0 -1
  404. package/dist/components/trace-viewer/index.js +0 -4
  405. package/dist/components/trace-viewer/index.js.map +0 -1
  406. package/dist/components/trace-viewer/trace-viewer.js.map +0 -1
  407. package/dist/components/trace-viewer/trace-viewer.module.css +0 -1465
  408. package/dist/components/trace-viewer/types.js.map +0 -1
  409. package/dist/components/trace-viewer/util/constants.d.ts +0 -9
  410. package/dist/components/trace-viewer/util/constants.d.ts.map +0 -1
  411. package/dist/components/trace-viewer/util/constants.js +0 -9
  412. package/dist/components/trace-viewer/util/constants.js.map +0 -1
  413. package/dist/components/trace-viewer/util/scrollbar-width.d.ts +0 -2
  414. package/dist/components/trace-viewer/util/scrollbar-width.d.ts.map +0 -1
  415. package/dist/components/trace-viewer/util/scrollbar-width.js +0 -14
  416. package/dist/components/trace-viewer/util/scrollbar-width.js.map +0 -1
  417. package/dist/components/trace-viewer/util/timing.js.map +0 -1
  418. package/dist/components/trace-viewer/util/tree.d.ts +0 -13
  419. package/dist/components/trace-viewer/util/tree.d.ts.map +0 -1
  420. package/dist/components/trace-viewer/util/tree.js +0 -227
  421. package/dist/components/trace-viewer/util/tree.js.map +0 -1
  422. package/dist/components/trace-viewer/util/use-immediate-style.d.ts +0 -15
  423. package/dist/components/trace-viewer/util/use-immediate-style.d.ts.map +0 -1
  424. package/dist/components/trace-viewer/util/use-immediate-style.js +0 -23
  425. package/dist/components/trace-viewer/util/use-immediate-style.js.map +0 -1
  426. package/dist/components/trace-viewer/util/use-streaming-spans.d.ts +0 -8
  427. package/dist/components/trace-viewer/util/use-streaming-spans.d.ts.map +0 -1
  428. package/dist/components/trace-viewer/util/use-streaming-spans.js +0 -345
  429. package/dist/components/trace-viewer/util/use-streaming-spans.js.map +0 -1
  430. package/dist/components/trace-viewer/util/use-trackpad-zoom.d.ts +0 -6
  431. package/dist/components/trace-viewer/util/use-trackpad-zoom.d.ts.map +0 -1
  432. package/dist/components/trace-viewer/util/use-trackpad-zoom.js +0 -39
  433. package/dist/components/trace-viewer/util/use-trackpad-zoom.js.map +0 -1
  434. package/dist/components/trace-viewer/worker.d.ts +0 -2
  435. package/dist/components/trace-viewer/worker.d.ts.map +0 -1
  436. package/dist/components/trace-viewer/worker.js +0 -109
  437. package/dist/components/trace-viewer/worker.js.map +0 -1
  438. package/dist/components/trace-viewer-new.d.ts.map +0 -1
  439. package/dist/components/trace-viewer-new.js +0 -23
  440. package/dist/components/trace-viewer-new.js.map +0 -1
  441. package/dist/components/ui/alert.js.map +0 -1
  442. package/dist/components/ui/card.js.map +0 -1
  443. package/dist/components/ui/data-inspector.js.map +0 -1
  444. package/dist/components/ui/decrypt-button.js.map +0 -1
  445. package/dist/components/ui/error-card.js.map +0 -1
  446. package/dist/components/ui/error-stack-block.js.map +0 -1
  447. package/dist/components/ui/inspector-theme.d.ts +0 -95
  448. package/dist/components/ui/inspector-theme.d.ts.map +0 -1
  449. package/dist/components/ui/inspector-theme.js +0 -82
  450. package/dist/components/ui/inspector-theme.js.map +0 -1
  451. package/dist/components/ui/load-more-button.js.map +0 -1
  452. package/dist/components/ui/menu-dropdown.js.map +0 -1
  453. package/dist/components/ui/skeleton.js.map +0 -1
  454. package/dist/components/ui/spinner.js.map +0 -1
  455. package/dist/components/ui/timestamp-tooltip.js.map +0 -1
  456. package/dist/components/workflow-trace-view.d.ts +0 -40
  457. package/dist/components/workflow-trace-view.d.ts.map +0 -1
  458. package/dist/components/workflow-trace-view.js +0 -695
  459. package/dist/components/workflow-trace-view.js.map +0 -1
  460. package/dist/components/workflow-traces/event-colors.js.map +0 -1
  461. package/dist/components/workflow-traces/trace-colors.d.ts +0 -15
  462. package/dist/components/workflow-traces/trace-colors.d.ts.map +0 -1
  463. package/dist/components/workflow-traces/trace-colors.js +0 -87
  464. package/dist/components/workflow-traces/trace-colors.js.map +0 -1
  465. package/dist/components/workflow-traces/trace-span-construction.js.map +0 -1
  466. package/dist/components/workflow-traces/trace-time-utils.js.map +0 -1
  467. package/dist/hooks/use-dark-mode.js.map +0 -1
  468. package/dist/index.js.map +0 -1
  469. package/dist/lib/event-analysis.js.map +0 -1
  470. package/dist/lib/event-materialization.js.map +0 -1
  471. package/dist/lib/hydration.js.map +0 -1
  472. package/dist/lib/stream-display.js.map +0 -1
  473. package/dist/lib/toast.js.map +0 -1
  474. package/dist/lib/trace-builder.js.map +0 -1
  475. package/dist/lib/utils.js.map +0 -1
  476. package/src/components/new-trace-viewer/components/event-list.tsx +0 -116
  477. package/src/components/new-trace-viewer/components/split-pane.tsx +0 -185
  478. package/src/components/new-trace-viewer/components/timeline.tsx +0 -382
  479. package/src/components/new-trace-viewer/context.tsx +0 -92
  480. package/src/components/new-trace-viewer/detail-panel.tsx +0 -58
  481. package/src/components/new-trace-viewer/trace-viewer.tsx +0 -645
  482. package/src/components/new-trace-viewer/types.ts +0 -0
  483. package/src/components/new-trace-viewer/util/constants.ts +0 -0
  484. package/src/components/run-trace-view.tsx +0 -84
  485. package/src/components/sidebar/detail-card.tsx +0 -65
  486. package/src/components/trace-viewer/components/map.tsx +0 -226
  487. package/src/components/trace-viewer/components/markers.tsx +0 -612
  488. package/src/components/trace-viewer/components/node.tsx +0 -505
  489. package/src/components/trace-viewer/components/search-input.tsx +0 -52
  490. package/src/components/trace-viewer/components/search.tsx +0 -47
  491. package/src/components/trace-viewer/components/span-content.tsx +0 -247
  492. package/src/components/trace-viewer/components/span-detail-panel.tsx +0 -655
  493. package/src/components/trace-viewer/components/span-segments.ts +0 -585
  494. package/src/components/trace-viewer/components/span-strategies.ts +0 -205
  495. package/src/components/trace-viewer/components/ui.tsx +0 -156
  496. package/src/components/trace-viewer/components/zoom-button.tsx +0 -61
  497. package/src/components/trace-viewer/components/zoom-icons.tsx +0 -65
  498. package/src/components/trace-viewer/index.tsx +0 -4
  499. package/src/components/trace-viewer/trace-viewer.module.css +0 -1465
  500. package/src/components/trace-viewer/util/constants.ts +0 -8
  501. package/src/components/trace-viewer/util/scrollbar-width.ts +0 -13
  502. package/src/components/trace-viewer/util/tree.ts +0 -277
  503. package/src/components/trace-viewer/util/use-immediate-style.ts +0 -38
  504. package/src/components/trace-viewer/util/use-streaming-spans.ts +0 -426
  505. package/src/components/trace-viewer/util/use-trackpad-zoom.tsx +0 -51
  506. package/src/components/trace-viewer/worker.ts +0 -131
  507. package/src/components/ui/inspector-theme.ts +0 -110
  508. package/src/components/workflow-trace-view.tsx +0 -1171
  509. package/src/components/workflow-traces/trace-colors.ts +0 -112
  510. /package/dist/components/{new-trace-viewer → trace-viewer}/components/copy-button.d.ts +0 -0
  511. /package/dist/components/{new-trace-viewer → trace-viewer}/components/middle-truncate/copy-selection.d.ts +0 -0
  512. /package/dist/components/{new-trace-viewer → trace-viewer}/components/middle-truncate/middle-truncate.d.ts +0 -0
  513. /package/dist/components/{new-trace-viewer → trace-viewer}/components/middle-truncate/use-middle-truncate.d.ts +0 -0
  514. /package/dist/components/{new-trace-viewer → trace-viewer}/icons.d.ts +0 -0
  515. /package/src/components/{new-trace-viewer → trace-viewer}/components/middle-truncate/copy-selection.ts +0 -0
  516. /package/src/components/{new-trace-viewer → trace-viewer}/components/middle-truncate/use-middle-truncate.ts +0 -0
  517. /package/src/{components/trace-viewer/modules.d.ts → modules.d.ts} +0 -0
@@ -0,0 +1,784 @@
1
+ 'use client';
2
+
3
+ import { Root as SlotRoot, Slottable } from '@radix-ui/react-slot';
4
+ import type { JSX, MutableRefObject, ReactNode, RefObject } from 'react';
5
+ import {
6
+ createContext,
7
+ useContext,
8
+ useEffect,
9
+ useId,
10
+ useMemo,
11
+ useRef,
12
+ useState,
13
+ } from 'react';
14
+ import { createPortal } from 'react-dom';
15
+ import useMeasure from 'react-use-measure';
16
+ import { useReducedMotion } from '../../hooks/use-reduced-motion';
17
+ import { cn } from '../../lib/cn';
18
+
19
+ const INACTIVE_TIMEOUT_MS = 250;
20
+ const ENTER_DELAY_MS = 0;
21
+ const OPEN_DELAY_MS = 150;
22
+ const MAX_TRANSITION_DISTANCE_PX = 150;
23
+ const MAX_OVERLAP_FOR_TRANSITION_PERCENT = 100;
24
+ const PERSIST_TIMEOUT_MS = 1000;
25
+
26
+ interface Point {
27
+ x: number;
28
+ y: number;
29
+ }
30
+
31
+ interface ContextCardData {
32
+ id: string;
33
+ origin: Point;
34
+ contentSize: { width: number; height: number };
35
+ side: Side;
36
+ arrowOffset: Point;
37
+ }
38
+
39
+ type NullString = string | null;
40
+
41
+ interface ContextCardContextType {
42
+ rootOrigin: Point;
43
+ rootBounds: { width: number; height: number };
44
+ portalRef: RefObject<HTMLDivElement | null>;
45
+ activeId: RefObject<NullString | null>;
46
+ setActiveId: (id: NullString) => void;
47
+ hoveredId: NullString;
48
+ setHoveredId: (id: NullString) => void;
49
+ updateActiveContextCard: (update: ContextCardData | null) => void;
50
+ skipTransition: boolean;
51
+ rootVisible: boolean;
52
+ distanceFromLast: number;
53
+ lastOrigin: Point | null;
54
+ /** Whether a real {@link ContextCardProvider} is mounted above this consumer. */
55
+ isProvided: boolean;
56
+ }
57
+
58
+ const ContextCardContext = createContext<ContextCardContextType>({
59
+ rootOrigin: { x: 0, y: 0 },
60
+ rootBounds: { width: 0, height: 0 },
61
+ portalRef: null as unknown as RefObject<HTMLDivElement | null>,
62
+ activeId: null as unknown as MutableRefObject<string | null>,
63
+ setActiveId: () => void 0,
64
+ hoveredId: null,
65
+ setHoveredId: () => void 0,
66
+ updateActiveContextCard: () => void 0,
67
+ skipTransition: false,
68
+ rootVisible: false,
69
+ distanceFromLast: 0,
70
+ lastOrigin: null,
71
+ isProvided: false,
72
+ });
73
+ ContextCardContext.displayName = 'ContextCardContext';
74
+
75
+ /**
76
+ * Returns whether the current subtree is wrapped in a {@link ContextCardProvider}.
77
+ */
78
+ export function useHasContextCardProvider(): boolean {
79
+ return useContext(ContextCardContext).isProvided;
80
+ }
81
+
82
+ function usePrevious<T>(value: T): T | null {
83
+ const ref = useRef<T | null>(null);
84
+ useEffect(() => {
85
+ ref.current = value;
86
+ });
87
+ return ref.current;
88
+ }
89
+
90
+ function isRefObject(
91
+ value: HTMLElement | RefObject<HTMLElement | null> | null | undefined
92
+ ): value is RefObject<HTMLElement | null> {
93
+ return value !== null && value !== undefined && 'current' in value;
94
+ }
95
+
96
+ /**
97
+ * Provides shared state and a portal container for {@link ContextCardTrigger}
98
+ * components. Must wrap any tree containing triggers; manages positioning,
99
+ * visibility transitions, and the animated arrow tip across all cards.
100
+ */
101
+ export function ContextCardProvider({
102
+ children,
103
+ portalTarget,
104
+ }: {
105
+ children: ReactNode;
106
+ /** Custom container for the portal. Accepts either an element or a ref. */
107
+ portalTarget?: HTMLElement | RefObject<HTMLElement | null> | null;
108
+ }): ReactNode {
109
+ const [isMounted, setIsMounted] = useState(false);
110
+ useEffect(() => setIsMounted(true), []);
111
+ const resolvedPortalTarget = isRefObject(portalTarget)
112
+ ? portalTarget.current
113
+ : portalTarget;
114
+ const [ref, bounds] = useMeasure();
115
+ const portalRef = useRef<HTMLDivElement | null>(null);
116
+ const [activeContextCard, setActiveContextCard] =
117
+ useState<ContextCardData | null>(null);
118
+ const [visible, setVisible] = useState(false);
119
+ const [hoveredId, setHoveredId] = useState<NullString>(null);
120
+ const activeId = useRef<NullString>(null);
121
+
122
+ function setActiveId(id: NullString): void {
123
+ activeId.current = id;
124
+ setVisible(id !== null);
125
+ }
126
+ const updateActiveContextCard = (update: ContextCardData | null): void => {
127
+ if (update?.id !== activeId.current && update !== null) return;
128
+ setActiveContextCard(update);
129
+ };
130
+
131
+ const BORDER_WIDTH = 1;
132
+
133
+ const activeBounds = useMemo(() => {
134
+ if (!activeContextCard)
135
+ return {
136
+ width: 0,
137
+ height: 0,
138
+ x: 0,
139
+ y: 0,
140
+ side: 'top' as Side,
141
+ arrowOffset: { x: 0, y: 0 },
142
+ };
143
+ return {
144
+ width: activeContextCard.contentSize.width + BORDER_WIDTH * 2,
145
+ height: activeContextCard.contentSize.height + BORDER_WIDTH * 2,
146
+ x: activeContextCard.origin.x,
147
+ y: activeContextCard.origin.y,
148
+ side: activeContextCard.side,
149
+ arrowOffset: activeContextCard.arrowOffset,
150
+ };
151
+ }, [activeContextCard]);
152
+
153
+ const lastBounds = usePrevious(activeBounds);
154
+ const lastId = usePrevious(activeId.current);
155
+
156
+ const percentOverlapFromLast = useMemo(() => {
157
+ if (!lastBounds) return 0;
158
+
159
+ const overlapLeft = Math.max(activeBounds.x, lastBounds.x);
160
+ const overlapRight = Math.min(
161
+ activeBounds.x + activeBounds.width,
162
+ lastBounds.x + lastBounds.width
163
+ );
164
+ const overlapTop = Math.max(activeBounds.y, lastBounds.y);
165
+ const overlapBottom = Math.min(
166
+ activeBounds.y + activeBounds.height,
167
+ lastBounds.y + lastBounds.height
168
+ );
169
+
170
+ if (overlapLeft < overlapRight && overlapTop < overlapBottom) {
171
+ const overlapArea =
172
+ (overlapRight - overlapLeft) * (overlapBottom - overlapTop);
173
+
174
+ const activeBoundsArea = activeBounds.width * activeBounds.height;
175
+
176
+ if (activeBoundsArea === 0) return 0;
177
+
178
+ return (overlapArea / activeBoundsArea) * 100;
179
+ }
180
+
181
+ return 0;
182
+ }, [activeBounds, lastBounds]);
183
+
184
+ const distanceFromLast = useMemo(
185
+ () =>
186
+ Math.sqrt(
187
+ ((lastBounds?.x ?? 0) - activeBounds.x) ** 2 +
188
+ ((lastBounds?.y ?? 0) - activeBounds.y) ** 2
189
+ ),
190
+ [activeBounds.x, activeBounds.y, lastBounds?.x, lastBounds?.y]
191
+ );
192
+
193
+ const lastOrigin = useMemo(() => {
194
+ if (!lastBounds) return null;
195
+ return {
196
+ x: lastBounds.x - activeBounds.x,
197
+ y: lastBounds.y - activeBounds.y,
198
+ };
199
+ }, [activeBounds, lastBounds]);
200
+
201
+ const [isScrolling, setIsScrolling] = useState(false);
202
+ const skipTransition = useMemo(
203
+ () =>
204
+ distanceFromLast > MAX_TRANSITION_DISTANCE_PX ||
205
+ percentOverlapFromLast > MAX_OVERLAP_FOR_TRANSITION_PERCENT ||
206
+ lastId === null ||
207
+ isScrolling,
208
+ [distanceFromLast, isScrolling, lastId, percentOverlapFromLast]
209
+ );
210
+
211
+ useEffect(() => {
212
+ let isScrollingTimeout: ReturnType<typeof setTimeout> | null = null;
213
+
214
+ const onScroll = (): void => {
215
+ if (isScrollingTimeout) window.clearTimeout(isScrollingTimeout);
216
+
217
+ isScrollingTimeout = setTimeout(() => {
218
+ setIsScrolling(false);
219
+ }, 66);
220
+
221
+ if (!isScrolling) {
222
+ setIsScrolling(true);
223
+ }
224
+ };
225
+
226
+ document.addEventListener('scroll', onScroll, true);
227
+
228
+ return () => {
229
+ document.removeEventListener('scroll', onScroll, true);
230
+ };
231
+ }, [isScrolling]);
232
+
233
+ const contextValue = useMemo(
234
+ () => ({
235
+ updateActiveContextCard,
236
+ rootOrigin: { ...activeBounds },
237
+ rootBounds: bounds,
238
+ portalRef,
239
+ setActiveId,
240
+ activeId,
241
+ setHoveredId,
242
+ hoveredId,
243
+ skipTransition,
244
+ rootVisible: visible,
245
+ distanceFromLast,
246
+ lastOrigin,
247
+ isProvided: true,
248
+ }),
249
+ [
250
+ activeBounds,
251
+ bounds,
252
+ hoveredId,
253
+ skipTransition,
254
+ visible,
255
+ distanceFromLast,
256
+ lastOrigin,
257
+ ]
258
+ );
259
+
260
+ return (
261
+ <ContextCardContext.Provider value={contextValue}>
262
+ {children}
263
+ {isMounted
264
+ ? createPortal(
265
+ <div
266
+ className="w-full h-full inset-0 fixed pointer-events-none z-[100000]"
267
+ ref={ref}
268
+ >
269
+ <div
270
+ className="min-w-max transition-all duration-150 ease-[easing-function:cubic-bezier(0.3,_0.57,_0.07,_0.95)] will-change-[transform,width,height] motion-reduce:!transition-none"
271
+ style={{
272
+ opacity: visible ? 1 : 0,
273
+ }}
274
+ >
275
+ <div
276
+ className={cn(
277
+ 'absolute bg-background-100 bg-clip-padding rounded-[6px] overflow-visible pointer-events-none z-[1000000] shadow-[var(--ds-shadow-tooltip),0_0_0_1px_var(--ds-background-100)] w-fit [--context-card-tip-stroke:#DBDBDB] dark-theme:[--context-card-tip-stroke:#252525]',
278
+ skipTransition
279
+ ? '!transition-none'
280
+ : 'transition-[transform,width,height] duration-250 ease-[easing-function:cubic-bezier(0.29,0.31,0.05,0.96)] will-change-[transform,width,height] motion-reduce:!transition-none'
281
+ )}
282
+ data-skip-transition={skipTransition}
283
+ style={{
284
+ transform: `translate(${activeBounds.x}px,${activeBounds.y}px)`,
285
+ width: activeBounds.width,
286
+ height: activeBounds.height,
287
+ }}
288
+ >
289
+ <div
290
+ className={cn(
291
+ 'w-[14px] h-[7px] absolute grid place-content-center z-[999999999] origin-center',
292
+ {
293
+ 'top-full -translate-x-1/2 rotate-0':
294
+ activeBounds.side === 'top',
295
+ 'right-full -translate-y-1/2 rotate-90 -mr-[3.5px]':
296
+ activeBounds.side === 'right',
297
+ 'bottom-full -translate-x-1/2 rotate-180':
298
+ activeBounds.side === 'bottom',
299
+ 'left-full -translate-y-1/2 rotate-[270deg] -ml-[3.5px]':
300
+ activeBounds.side === 'left',
301
+ },
302
+ skipTransition
303
+ ? '!transition-none'
304
+ : 'transition-[transform,width,height] duration-250 ease-[easing-function:cubic-bezier(0.29,0.31,0.05,0.96)] will-change-[transform,width,height] motion-reduce:!transition-none'
305
+ )}
306
+ style={{
307
+ ...(activeBounds.side === 'top' ||
308
+ activeBounds.side === 'bottom'
309
+ ? {
310
+ left: `calc(50% + ${activeBounds.arrowOffset.x}px)`,
311
+ }
312
+ : {
313
+ top: `calc(50% + ${activeBounds.arrowOffset.y}px)`,
314
+ }),
315
+ }}
316
+ data-skip-transition={skipTransition}
317
+ data-side={activeBounds.side}
318
+ >
319
+ <svg
320
+ width="14"
321
+ height="7"
322
+ viewBox="0 0 14 7"
323
+ fill="none"
324
+ xmlns="http://www.w3.org/2000/svg"
325
+ aria-hidden="true"
326
+ >
327
+ <g clipPath="url(#context-card-tip-clip)">
328
+ <path
329
+ d="M15 -0.5V0.5H12.9834L12.8184 0.508789C12.4377 0.550822 12.0853 0.738056 11.8359 1.03418L8.53027 4.95996C7.73114 5.90893 6.26886 5.90892 5.46973 4.95996L2.16406 1.03418C1.87905 0.695733 1.45907 0.5 1.0166 0.5H-1V-0.5H15Z"
330
+ fill="var(--ds-background-100)"
331
+ style={{
332
+ fill: 'var(--ds-background-100)',
333
+ fillOpacity: 1,
334
+ stroke: 'var(--context-card-tip-stroke)',
335
+ strokeOpacity: 1,
336
+ }}
337
+ />
338
+ </g>
339
+ <defs>
340
+ <clipPath id="context-card-tip-clip">
341
+ <rect
342
+ width="14"
343
+ height="7"
344
+ fill="white"
345
+ style={{ fill: 'white', fillOpacity: 1 }}
346
+ />
347
+ </clipPath>
348
+ </defs>
349
+ </svg>
350
+ </div>
351
+ <div ref={portalRef} />
352
+ </div>
353
+ </div>
354
+ </div>,
355
+ resolvedPortalTarget ?? document.body
356
+ )
357
+ : null}
358
+ </ContextCardContext.Provider>
359
+ );
360
+ }
361
+
362
+ export type Side = 'top' | 'bottom' | 'left' | 'right';
363
+ export type Align = 'start' | 'center' | 'end';
364
+
365
+ /** Props for the {@link ContextCardTrigger} component. */
366
+ export interface ContextCardTriggerProps
367
+ extends Omit<React.HTMLAttributes<HTMLDivElement>, 'content'> {
368
+ /** The content rendered inside the context card popup. */
369
+ content: ReactNode;
370
+ /** Which side of the trigger to display the card. Defaults to `"right"`. */
371
+ side?: Side;
372
+ /** Alignment of the card relative to the trigger. Defaults to `"center"`. */
373
+ align?: Align;
374
+ /** Distance in pixels between the trigger and the card. Defaults to `16`. */
375
+ sideOffset?: number;
376
+ /** Offset in pixels along the alignment axis. Defaults to `0`. */
377
+ alignOffset?: number;
378
+ /** Whether to disable pointer events on the card content. */
379
+ ignoreCardPointerEvents?: boolean;
380
+ /** Whether to remove default padding from the card content. */
381
+ noPadding?: boolean;
382
+ /** Whether the trigger uses the Slot pattern to merge props onto its child. */
383
+ asChild?: boolean;
384
+ /** Can be used to hide the card when needed. */
385
+ hide?: boolean;
386
+ /** Time in milliseconds before the card is dismissed after mouse leaves. */
387
+ inactiveTimeoutMs?: number;
388
+ }
389
+
390
+ /**
391
+ * Displays a floating context card on hover with viewport-aware collision
392
+ * detection and animated position transitions between triggers in the same
393
+ * {@link ContextCardProvider}. Persists briefly after mouse leave.
394
+ */
395
+ export function ContextCardTrigger({
396
+ content,
397
+ children,
398
+ side = 'right',
399
+ align = 'center',
400
+ sideOffset = 16,
401
+ alignOffset = 0,
402
+ ignoreCardPointerEvents = false,
403
+ noPadding,
404
+ asChild,
405
+ className,
406
+ hide,
407
+ inactiveTimeoutMs = INACTIVE_TIMEOUT_MS,
408
+ }: ContextCardTriggerProps): JSX.Element {
409
+ const triggerRef = useRef<HTMLDivElement>(null);
410
+ const contentRef = useRef<HTMLDivElement>(null);
411
+ const [contentMeasureRef, contentMeasureBounds] = useMeasure();
412
+ const {
413
+ portalRef,
414
+ updateActiveContextCard,
415
+ activeId,
416
+ setActiveId,
417
+ hoveredId,
418
+ setHoveredId,
419
+ skipTransition,
420
+ rootVisible,
421
+ } = useContext(ContextCardContext);
422
+ const id = useId();
423
+
424
+ useEffect(() => {
425
+ return () => {
426
+ // Only clear the shared active card if this trigger was the active one;
427
+ // otherwise an unmounting inactive trigger would hide another trigger's card.
428
+ if (activeId.current === id) {
429
+ setActiveId(null);
430
+ }
431
+ };
432
+ }, []);
433
+
434
+ const reduceMotion = useReducedMotion();
435
+
436
+ const [localHover, setLocalHover] = useState(false);
437
+ const [persisting, setPersisting] = useState(false);
438
+ const [visible, setVisible] = useState(false);
439
+
440
+ const activeTimeout = useRef<ReturnType<typeof setTimeout> | null>(null);
441
+ const persistingTimeout = useRef<ReturnType<typeof setTimeout> | null>(null);
442
+ const openTimeout = useRef<ReturnType<typeof setTimeout> | null>(null);
443
+
444
+ useEffect(() => {
445
+ if (
446
+ localHover &&
447
+ contentMeasureBounds.width > 0 &&
448
+ contentMeasureBounds.height > 0
449
+ ) {
450
+ if (openTimeout.current) clearTimeout(openTimeout.current);
451
+ openTimeout.current = setTimeout(
452
+ () => {
453
+ setActiveId(id);
454
+ updateBounds();
455
+ },
456
+ rootVisible ? 0 : OPEN_DELAY_MS
457
+ );
458
+ }
459
+ return () => {
460
+ if (openTimeout.current) clearTimeout(openTimeout.current);
461
+ };
462
+ }, [localHover, contentMeasureBounds]);
463
+
464
+ const enterTimeout = useRef<ReturnType<typeof setTimeout> | null>(null);
465
+
466
+ useEffect(() => {
467
+ if (enterTimeout.current) clearTimeout(enterTimeout.current);
468
+ if (hoveredId !== id) {
469
+ // Exits are instant
470
+ setVisible(false);
471
+ } else {
472
+ // Enters can be delayed unless we wish to script the transition
473
+ enterTimeout.current = setTimeout(
474
+ () => {
475
+ setVisible(true);
476
+ },
477
+ reduceMotion || skipTransition ? 0 : ENTER_DELAY_MS
478
+ );
479
+ }
480
+ }, [hoveredId, id, reduceMotion, skipTransition]);
481
+
482
+ function updateBounds(): void {
483
+ if (!contentRef.current) return;
484
+ const bounds = computeBounds();
485
+ updateActiveContextCard({ id, ...bounds });
486
+ }
487
+
488
+ function computeBounds(sideOverride?: Side): {
489
+ origin: Point;
490
+ contentSize: { width: number; height: number };
491
+ side: Side;
492
+ arrowOffset: Point;
493
+ } {
494
+ if (!triggerRef.current) throw new Error('Trigger not found');
495
+ if (!contentRef.current) throw new Error('Content not found');
496
+ const appliedSide = sideOverride ?? side;
497
+ const triggerRect = triggerRef.current.getBoundingClientRect();
498
+ const contentRect = contentRef.current.getBoundingClientRect();
499
+ contentRef.current.style.width = 'max-content';
500
+ contentRef.current.style.position = 'absolute';
501
+ const contentSize = {
502
+ width: Math.max(contentRect.width, contentRef.current.offsetWidth),
503
+ height: contentRect.height,
504
+ };
505
+
506
+ let origin: Point;
507
+
508
+ const arrowWidth = 14;
509
+ const halfArrowWidth = arrowWidth / 2;
510
+ const halfTriggerWidth = triggerRect.width / 2;
511
+ const halfTriggerHeight = triggerRect.height / 2;
512
+ const halfContentWidth = contentSize.width / 2;
513
+ const halfContentHeight = contentSize.height / 2;
514
+
515
+ const top = triggerRect.top;
516
+ const left = triggerRect.left;
517
+
518
+ let alignX = left + halfTriggerWidth - halfContentWidth + alignOffset;
519
+ if (align === 'start') alignX = left + alignOffset;
520
+ if (align === 'end')
521
+ alignX = left + triggerRect.width - contentRect.width + alignOffset;
522
+
523
+ let alignY = top + halfTriggerHeight - halfContentHeight + alignOffset;
524
+ if (align === 'start') alignY = top + alignOffset;
525
+ if (align === 'end')
526
+ alignY = top + triggerRect.height - contentRect.height + alignOffset;
527
+
528
+ switch (appliedSide) {
529
+ case 'top':
530
+ origin = {
531
+ x: alignX,
532
+ y: top - contentRect.height - sideOffset,
533
+ };
534
+ break;
535
+ case 'right':
536
+ origin = {
537
+ x: left + triggerRect.width + sideOffset,
538
+ y: alignY,
539
+ };
540
+ break;
541
+ case 'bottom':
542
+ origin = {
543
+ x: alignX,
544
+ y: top + triggerRect.height + sideOffset,
545
+ };
546
+ break;
547
+ case 'left':
548
+ origin = {
549
+ x: left - contentRect.width - sideOffset,
550
+ y: alignY,
551
+ };
552
+ break;
553
+ default: {
554
+ const _exhaustive: never = appliedSide;
555
+ throw new Error(`Unknown side: ${String(_exhaustive)}`);
556
+ }
557
+ }
558
+
559
+ const viewportWidth = document.documentElement.clientWidth;
560
+ const viewportHeight = document.documentElement.clientHeight;
561
+
562
+ const isOffscreenLeft = origin.x < 0;
563
+ const isOffscreenRight = origin.x + contentRect.width > viewportWidth;
564
+ const isOffscreenTop = origin.y < 0;
565
+ const isOffscreenBottom = origin.y + contentRect.height > viewportHeight;
566
+
567
+ if (!sideOverride) {
568
+ const spaceAbove = top;
569
+ const spaceBelow = viewportHeight - (top + triggerRect.height);
570
+ const spaceLeft = left;
571
+ const spaceRight = viewportWidth - (left + triggerRect.width);
572
+
573
+ if (side === 'top' && isOffscreenTop && spaceBelow > spaceAbove) {
574
+ return computeBounds('bottom');
575
+ }
576
+ if (side === 'bottom' && isOffscreenBottom && spaceAbove > spaceBelow) {
577
+ return computeBounds('top');
578
+ }
579
+
580
+ if (side === 'right' && isOffscreenRight && spaceLeft > spaceRight) {
581
+ return computeBounds('left');
582
+ }
583
+ if (side === 'left' && isOffscreenLeft && spaceRight > spaceLeft) {
584
+ return computeBounds('right');
585
+ }
586
+
587
+ if (
588
+ (side === 'top' || side === 'bottom') &&
589
+ isOffscreenLeft &&
590
+ spaceRight > contentRect.width
591
+ ) {
592
+ return computeBounds('right');
593
+ }
594
+ if (
595
+ (side === 'top' || side === 'bottom') &&
596
+ isOffscreenRight &&
597
+ spaceLeft > contentRect.width
598
+ ) {
599
+ return computeBounds('left');
600
+ }
601
+
602
+ if (
603
+ (side === 'left' || side === 'right') &&
604
+ isOffscreenTop &&
605
+ spaceBelow > contentRect.height
606
+ ) {
607
+ return computeBounds('bottom');
608
+ }
609
+ if (
610
+ (side === 'left' || side === 'right') &&
611
+ isOffscreenBottom &&
612
+ spaceAbove > contentRect.height
613
+ ) {
614
+ return computeBounds('top');
615
+ }
616
+ }
617
+
618
+ const viewportPadding = 8;
619
+ if (appliedSide === 'left' || appliedSide === 'right') {
620
+ origin.y = Math.max(
621
+ viewportPadding,
622
+ Math.min(
623
+ origin.y,
624
+ viewportHeight - contentSize.height - viewportPadding
625
+ )
626
+ );
627
+ } else {
628
+ origin.x = Math.max(
629
+ viewportPadding,
630
+ Math.min(origin.x, viewportWidth - contentSize.width - viewportPadding)
631
+ );
632
+ }
633
+
634
+ // Always constrain Y position within viewport bounds
635
+ origin.y = Math.max(
636
+ viewportPadding,
637
+ Math.min(origin.y, viewportHeight - contentSize.height - viewportPadding)
638
+ );
639
+
640
+ const triggerCenterX = left + halfTriggerWidth;
641
+ const triggerCenterY = top + halfTriggerHeight;
642
+ const cardCenterX = origin.x + contentSize.width / 2;
643
+ const cardCenterY = origin.y + contentSize.height / 2;
644
+
645
+ let arrowOffsetX = triggerCenterX - cardCenterX;
646
+ let arrowOffsetY = triggerCenterY - cardCenterY;
647
+
648
+ // Clamp arrow offset to ensure it stays within card boundaries.
649
+ // Arrow should be at least halfArrowWidth (7px) from the card edges.
650
+ const maxArrowOffsetX = halfContentWidth - halfArrowWidth;
651
+ const maxArrowOffsetY = halfContentHeight - halfArrowWidth;
652
+
653
+ if (appliedSide === 'top' || appliedSide === 'bottom') {
654
+ arrowOffsetX = Math.max(
655
+ -maxArrowOffsetX,
656
+ Math.min(arrowOffsetX, maxArrowOffsetX)
657
+ );
658
+ }
659
+
660
+ if (appliedSide === 'left' || appliedSide === 'right') {
661
+ arrowOffsetY = Math.max(
662
+ -maxArrowOffsetY,
663
+ Math.min(arrowOffsetY, maxArrowOffsetY)
664
+ );
665
+ }
666
+
667
+ const arrowOffset = {
668
+ x: arrowOffsetX,
669
+ y: arrowOffsetY,
670
+ };
671
+
672
+ return { origin, contentSize, side: appliedSide, arrowOffset };
673
+ }
674
+
675
+ useEffect(() => {
676
+ document.addEventListener('scroll', updateBounds, true);
677
+ window.addEventListener('resize', updateBounds);
678
+ return () => {
679
+ document.removeEventListener('scroll', updateBounds, true);
680
+ window.removeEventListener('resize', updateBounds);
681
+ };
682
+ }, []);
683
+
684
+ function resetDestructiveTimeouts(): void {
685
+ if (activeTimeout.current) clearTimeout(activeTimeout.current);
686
+ if (persistingTimeout.current) clearTimeout(persistingTimeout.current);
687
+ if (openTimeout.current) clearTimeout(openTimeout.current);
688
+ }
689
+
690
+ function attemptDeactivate(): void {
691
+ if (activeTimeout.current) clearTimeout(activeTimeout.current);
692
+ activeTimeout.current = setTimeout(() => {
693
+ if (activeId.current !== id) return;
694
+ setActiveId(null);
695
+ }, inactiveTimeoutMs);
696
+ }
697
+
698
+ function attemptPersist(): void {
699
+ setPersisting(true);
700
+ if (persistingTimeout.current) clearTimeout(persistingTimeout.current);
701
+ persistingTimeout.current = setTimeout(() => {
702
+ setPersisting(false);
703
+ }, PERSIST_TIMEOUT_MS);
704
+ }
705
+
706
+ function onMouseEnter(): void {
707
+ resetDestructiveTimeouts();
708
+ setHoveredId(id);
709
+ setLocalHover(true);
710
+ }
711
+
712
+ function onMouseLeave(): void {
713
+ setLocalHover(false);
714
+ attemptDeactivate();
715
+ attemptPersist();
716
+ }
717
+
718
+ useEffect(() => {
719
+ // close instantly
720
+ if (hide) {
721
+ setLocalHover(false);
722
+ setActiveId(null);
723
+ }
724
+ }, [hide, setActiveId]);
725
+
726
+ function handleClick(e: React.MouseEvent): void {
727
+ // Close if clicking a link. We assume we want the card to disappear if navigating.
728
+ if (e.target instanceof HTMLElement && e.target.closest('a[href]')) {
729
+ onMouseLeave();
730
+ }
731
+ }
732
+
733
+ const Comp = asChild ? SlotRoot : 'div';
734
+
735
+ return (
736
+ <Comp
737
+ className={cn(
738
+ 'inline-flex cursor-pointer flex-[0_1_auto] overflow-hidden',
739
+ className
740
+ )}
741
+ onMouseEnter={onMouseEnter}
742
+ onMouseLeave={onMouseLeave}
743
+ onClick={handleClick}
744
+ ref={triggerRef}
745
+ >
746
+ <Slottable>{children}</Slottable>
747
+ {portalRef?.current && (localHover || persisting)
748
+ ? createPortal(
749
+ <div
750
+ className={cn(
751
+ 'absolute top-0 p-3 left-0 max-w-max transition-[transform,width,height] duration-250 ease-[easing-function:cubic-bezier(0.29,0.31,0.05,0.96)] will-change-[transform,width,height] motion-reduce:!transition-none',
752
+ skipTransition && '!transition-none'
753
+ )}
754
+ key={id}
755
+ ref={contentRef}
756
+ style={{
757
+ ...(noPadding ? { padding: 0 } : {}),
758
+ pointerEvents:
759
+ rootVisible && visible && !ignoreCardPointerEvents
760
+ ? 'all'
761
+ : 'none',
762
+ }}
763
+ >
764
+ <div
765
+ className={cn(
766
+ 'min-w-max transition-all duration-150 ease-[easing-function:cubic-bezier(0.3,_0.57,_0.07,_0.95)] will-change-[transform,width,height] motion-reduce:!transition-none',
767
+ skipTransition
768
+ ? '!transition-none'
769
+ : 'transition-[transform,width,height] duration-250 ease-[easing-function:cubic-bezier(0.29,0.31,0.05,0.96)] will-change-[transform,width,height] motion-reduce:!transition-none'
770
+ )}
771
+ ref={contentMeasureRef}
772
+ style={{
773
+ opacity: Number(visible),
774
+ }}
775
+ >
776
+ {content}
777
+ </div>
778
+ </div>,
779
+ portalRef.current
780
+ )
781
+ : null}
782
+ </Comp>
783
+ );
784
+ }