@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
@@ -1,43 +1,38 @@
1
1
  'use client';
2
2
 
3
3
  /**
4
- * Reusable data inspector component built on react-inspector.
4
+ * Reusable data inspector for the o11y UI.
5
5
  *
6
- * All data rendering in the o11y UI should use this component to ensure
7
- * consistent theming, custom type handling (StreamRef, ClassInstanceRef),
8
- * and expand behavior.
6
+ * Renders JSON as a collapsible tree: bracket notation (`{ }` / `[ … ]`),
7
+ * colored keys, typed value colors, `▸`/`▾` disclosure icons, and a `...`
8
+ * collapsed indicator.
9
+ *
10
+ * On top of plain JSON it handles the workflow-specific value types: StreamRef /
11
+ * RunRef badges, encrypted markers, decoded byte streams, Dates, and named
12
+ * class instances.
9
13
  */
10
14
 
11
15
  import { Lock } from 'lucide-react';
12
16
  import {
13
17
  createContext,
18
+ type KeyboardEvent as ReactKeyboardEvent,
19
+ type MouseEvent as ReactMouseEvent,
20
+ type ReactNode,
21
+ type RefObject,
14
22
  useContext,
15
- useEffect,
23
+ useId,
16
24
  useMemo,
17
25
  useRef,
18
26
  useState,
19
27
  } from 'react';
20
- import {
21
- ObjectInspector,
22
- ObjectLabel,
23
- ObjectName,
24
- ObjectRootLabel,
25
- ObjectValue,
26
- } from 'react-inspector';
27
- import { useDarkMode } from '../../hooks/use-dark-mode';
28
28
  import { ENCRYPTED_DISPLAY_NAME } from '../../lib/hydration';
29
29
  import {
30
30
  type DecodedStreamChunkSource,
31
31
  type FormattedStreamChunkDisplay,
32
32
  formatArrayBufferViewForDisplay,
33
33
  } from '../../lib/stream-display';
34
- import {
35
- type InspectorThemeExtended,
36
- inspectorThemeDark,
37
- inspectorThemeExtendedDark,
38
- inspectorThemeExtendedLight,
39
- inspectorThemeLight,
40
- } from './inspector-theme';
34
+ import { Button } from './button';
35
+ import { CLS, JSON_VIEW_STYLES } from './data-inspector.styles';
41
36
  import { Spinner } from './spinner';
42
37
 
43
38
  // ---------------------------------------------------------------------------
@@ -66,6 +61,13 @@ interface BytesDisplay {
66
61
  decodedFrom?: DecodedStreamChunkSource;
67
62
  }
68
63
 
64
+ interface ClassInstanceRef {
65
+ __type: typeof CLASS_INSTANCE_REF_TYPE;
66
+ className: string;
67
+ classId: string;
68
+ data: unknown;
69
+ }
70
+
69
71
  function deserializeChunkText(text: string): string {
70
72
  try {
71
73
  const parsed = JSON.parse(text);
@@ -105,12 +107,7 @@ export function isBytesDisplay(value: unknown): value is BytesDisplay {
105
107
  return desc?.value === BYTES_DISPLAY_TYPE;
106
108
  }
107
109
 
108
- function isClassInstanceRef(value: unknown): value is {
109
- __type: string;
110
- className: string;
111
- classId: string;
112
- data: unknown;
113
- } {
110
+ function isClassInstanceRef(value: unknown): value is ClassInstanceRef {
114
111
  return (
115
112
  value !== null &&
116
113
  typeof value === 'object' &&
@@ -119,6 +116,15 @@ function isClassInstanceRef(value: unknown): value is {
119
116
  );
120
117
  }
121
118
 
119
+ function isEncryptedMarker(value: unknown): boolean {
120
+ return (
121
+ value !== null &&
122
+ typeof value === 'object' &&
123
+ (value as { constructor?: { name?: string } }).constructor?.name ===
124
+ ENCRYPTED_DISPLAY_NAME
125
+ );
126
+ }
127
+
122
128
  // ---------------------------------------------------------------------------
123
129
  // Stream click context (passed through from the panel)
124
130
  // ---------------------------------------------------------------------------
@@ -138,6 +144,7 @@ export const StreamClickContext = createContext<
138
144
  export type DecryptClickContextValue = {
139
145
  onDecrypt: () => void;
140
146
  isDecrypting: boolean;
147
+ hasEncryptedData?: boolean;
141
148
  };
142
149
 
143
150
  export const DecryptClickContext = createContext<
@@ -148,37 +155,30 @@ export const RunClickContext = createContext<
148
155
  ((runId: string) => void) | undefined
149
156
  >(undefined);
150
157
 
158
+ // ---------------------------------------------------------------------------
159
+ // Workflow-specific value renderers (badges, encrypted markers, byte streams)
160
+ // ---------------------------------------------------------------------------
161
+
151
162
  function EncryptedInlineLabel() {
152
163
  const ctx = useContext(DecryptClickContext);
153
164
  if (ctx) {
154
165
  return (
155
- <button
156
- type="button"
157
- className="inline-flex items-center gap-1 px-1.5 py-0.5 rounded text-[11px] cursor-pointer"
158
- style={{
159
- backgroundColor: 'var(--ds-gray-100)',
160
- color: 'var(--ds-gray-700)',
161
- border: '1px solid var(--ds-gray-400)',
162
- fontStyle: 'italic',
163
- opacity: ctx.isDecrypting ? 0.6 : 1,
164
- }}
166
+ <Button
167
+ size="xs"
168
+ className="align-baseline gap-x-1"
165
169
  disabled={ctx.isDecrypting}
166
170
  onClick={(e) => {
167
171
  e.stopPropagation();
168
172
  ctx.onDecrypt();
169
173
  }}
170
- title="Click to decrypt"
171
174
  >
172
175
  {ctx.isDecrypting ? (
173
- <Spinner size={12} />
176
+ <Spinner size={10} />
174
177
  ) : (
175
- <Lock
176
- className="h-3 w-3"
177
- style={{ display: 'inline', flexShrink: 0 }}
178
- />
178
+ <Lock className="h-3 w-3" />
179
179
  )}
180
- <span>{ctx.isDecrypting ? 'Decrypting…' : 'Decrypt'}</span>
181
- </button>
180
+ <span>Decrypt</span>
181
+ </Button>
182
182
  );
183
183
  }
184
184
  return (
@@ -196,6 +196,7 @@ function EncryptedInlineLabel() {
196
196
  </span>
197
197
  );
198
198
  }
199
+
199
200
  function StreamRefInline({ streamRef }: { streamRef: StreamRef }) {
200
201
  const onStreamClick = useContext(StreamClickContext);
201
202
  const [hovered, setHovered] = useState(false);
@@ -249,14 +250,6 @@ function RunRefInline({ runRef }: { runRef: RunRef }) {
249
250
  );
250
251
  }
251
252
 
252
- // ---------------------------------------------------------------------------
253
- // Extended theme context (for colors react-inspector doesn't support natively)
254
- // ---------------------------------------------------------------------------
255
-
256
- const ExtendedThemeContext = createContext<InspectorThemeExtended>(
257
- inspectorThemeExtendedLight
258
- );
259
-
260
253
  function DecodedBytesChunk({
261
254
  decodedText,
262
255
  source,
@@ -370,162 +363,474 @@ function DecodedBytesInspector({
370
363
  );
371
364
  }
372
365
 
373
- function BytesDisplayLabel({
374
- name,
375
- display,
376
- }: {
377
- name?: string;
378
- display: BytesDisplay;
379
- }) {
366
+ function BytesDisplayValue({ display }: { display: BytesDisplay }) {
367
+ if (display.decodedFrom) {
368
+ return (
369
+ <DecodedBytesChunk
370
+ decodedText={display.text}
371
+ source={display.decodedFrom}
372
+ />
373
+ );
374
+ }
380
375
  return (
381
- <div className="inline-block min-w-0 align-top">
382
- {name != null && <ObjectName name={name} />}
383
- {name != null && <span>: </span>}
384
- {display.decodedFrom ? (
385
- <DecodedBytesChunk
386
- decodedText={display.text}
387
- source={display.decodedFrom}
388
- />
389
- ) : (
390
- <span
391
- className="whitespace-pre-wrap break-words"
392
- style={{ color: 'var(--ds-gray-1000)' }}
393
- >
394
- {display.text}
395
- </span>
396
- )}
397
- </div>
376
+ <span
377
+ className="whitespace-pre-wrap break-words"
378
+ style={{ color: 'var(--ds-gray-1000)' }}
379
+ >
380
+ {display.text}
381
+ </span>
398
382
  );
399
383
  }
400
384
 
401
385
  // ---------------------------------------------------------------------------
402
- // Custom nodeRenderer
386
+ // Tree renderer
403
387
  // ---------------------------------------------------------------------------
404
388
 
389
+ type Entry = [field: string | undefined, value: unknown];
390
+
391
+ interface NodeContext {
392
+ level: number;
393
+ shouldExpand: (level: number) => boolean;
394
+ outerRef: RefObject<HTMLDivElement | null>;
395
+ }
396
+
397
+ /** Field names are rendered unquoted (empty string shows as `""`). */
398
+ function formatField(field: string): string {
399
+ return field === '' ? '""' : field;
400
+ }
401
+
405
402
  /**
406
- * Extends the default react-inspector nodeRenderer with special handling
407
- * for ClassInstanceRef, StreamRef, and Date types.
408
- *
409
- * react-inspector renders Date instances as unstyled plain text (no theme
410
- * key exists for them), so we intercept here and apply the magenta color
411
- * from our extended theme — matching Node.js util.inspect()'s date style.
412
- *
413
- * Default nodeRenderer reference:
414
- * https://github.com/storybookjs/react-inspector/blob/main/README.md#noderenderer
403
+ * Describe an object/array/map/set as an expandable container. Returns null for
404
+ * values that should render as a primitive. `prefix` carries a class name shown
405
+ * before the opening bracket (Map/Set and named class instances).
415
406
  */
416
- function NodeRenderer({
417
- depth,
418
- name,
419
- data,
420
- isNonenumerable,
407
+ function describeContainer(
408
+ value: unknown
409
+ ): { entries: Entry[]; open: string; close: string; prefix?: string } | null {
410
+ if (Array.isArray(value)) {
411
+ return {
412
+ entries: value.map((item) => [undefined, item] as Entry),
413
+ open: '[',
414
+ close: ']',
415
+ };
416
+ }
417
+ if (value instanceof Map) {
418
+ return {
419
+ entries: Array.from(value.entries(), ([key, val]) => [
420
+ String(key),
421
+ val,
422
+ ]) as Entry[],
423
+ open: '{',
424
+ close: '}',
425
+ prefix: 'Map',
426
+ };
427
+ }
428
+ if (value instanceof Set) {
429
+ return {
430
+ entries: Array.from(value.values(), (item) => [undefined, item] as Entry),
431
+ open: '[',
432
+ close: ']',
433
+ prefix: 'Set',
434
+ };
435
+ }
436
+ if (value !== null && typeof value === 'object') {
437
+ const name = (value as { constructor?: { name?: string } }).constructor
438
+ ?.name;
439
+ return {
440
+ entries: Object.entries(value) as Entry[],
441
+ open: '{',
442
+ close: '}',
443
+ prefix: name && name !== 'Object' ? name : undefined,
444
+ };
445
+ }
446
+ return null;
447
+ }
448
+
449
+ function describePrimitive(value: unknown): { text: string; cls: string } {
450
+ if (value === null) return { text: 'null', cls: CLS.null };
451
+ if (value === undefined) return { text: 'undefined', cls: CLS.undefined };
452
+ if (typeof value === 'string' || value instanceof String) {
453
+ return { text: `"${String(value)}"`, cls: CLS.string };
454
+ }
455
+ if (typeof value === 'boolean' || value instanceof Boolean) {
456
+ return { text: String(value), cls: CLS.boolean };
457
+ }
458
+ if (typeof value === 'number' || value instanceof Number) {
459
+ return { text: String(value), cls: CLS.number };
460
+ }
461
+ if (typeof value === 'bigint') {
462
+ return { text: `${value.toString()}n`, cls: CLS.number };
463
+ }
464
+ return { text: String(value), cls: CLS.punctuation };
465
+ }
466
+
467
+ function Label({ field, clickable }: { field?: string; clickable?: boolean }) {
468
+ if (field === undefined) return null;
469
+ return (
470
+ <span className={clickable ? CLS.clickableLabel : CLS.label}>
471
+ {`${formatField(field)}:`}
472
+ </span>
473
+ );
474
+ }
475
+
476
+ function Comma({ isLast }: { isLast: boolean }) {
477
+ if (isLast) return null;
478
+ return <span className={CLS.punctuation}>,</span>;
479
+ }
480
+
481
+ /** A non-expandable row: `field: <value>`. */
482
+ function LeafRow({
483
+ field,
484
+ isLast,
485
+ children,
421
486
  }: {
422
- depth: number;
423
- name?: string;
424
- data: unknown;
425
- isNonenumerable?: boolean;
426
- expanded?: boolean;
487
+ field?: string;
488
+ isLast: boolean;
489
+ children: ReactNode;
427
490
  }) {
428
- const extendedTheme = useContext(ExtendedThemeContext);
491
+ return (
492
+ <div className={CLS.child} role="treeitem" tabIndex={-1}>
493
+ <Label field={field} />
494
+ {children}
495
+ <Comma isLast={isLast} />
496
+ </div>
497
+ );
498
+ }
429
499
 
430
- if (isBytesDisplay(data)) {
431
- return <BytesDisplayLabel name={name} display={data} />;
432
- }
500
+ function PrimitiveValue({ field, value, isLast }: NodeProps) {
501
+ const { text, cls } = describePrimitive(value);
502
+ return (
503
+ <LeafRow field={field} isLast={isLast}>
504
+ <span className={cls}>{text}</span>
505
+ </LeafRow>
506
+ );
507
+ }
508
+
509
+ function EmptyContainer({
510
+ field,
511
+ prefix,
512
+ open,
513
+ close,
514
+ isLast,
515
+ }: {
516
+ field?: string;
517
+ prefix?: string;
518
+ open: string;
519
+ close: string;
520
+ isLast: boolean;
521
+ }) {
522
+ return (
523
+ <div className={CLS.child} role="treeitem" tabIndex={-1}>
524
+ <Label field={field} />
525
+ {prefix ? <span className={CLS.className}>{prefix}</span> : null}
526
+ <span className={CLS.punctuation}>{open}</span>
527
+ <span className={CLS.punctuation}>{close}</span>
528
+ <Comma isLast={isLast} />
529
+ </div>
530
+ );
531
+ }
433
532
 
434
- // Encrypted marker → flat label with Lock icon, clickable when onDecrypt is available
435
- if (
436
- data !== null &&
437
- typeof data === 'object' &&
438
- data.constructor?.name === ENCRYPTED_DISPLAY_NAME
439
- ) {
440
- const label = <EncryptedInlineLabel />;
441
- if (depth === 0) {
442
- return label;
533
+ function focusExpander(
534
+ button: HTMLElement,
535
+ outerRef: RefObject<HTMLDivElement | null>
536
+ ) {
537
+ const previous = outerRef.current?.querySelector<HTMLElement>(
538
+ '[data-json-expander][tabindex="0"]'
539
+ );
540
+ if (previous) previous.tabIndex = -1;
541
+ button.tabIndex = 0;
542
+ button.focus();
543
+ }
544
+
545
+ function moveExpanderFocus(
546
+ outerRef: RefObject<HTMLDivElement | null>,
547
+ direction: 1 | -1
548
+ ) {
549
+ const root = outerRef.current;
550
+ if (!root) return;
551
+ const buttons = root.querySelectorAll<HTMLElement>('[data-json-expander]');
552
+ let current = -1;
553
+ for (let i = 0; i < buttons.length; i += 1) {
554
+ if (buttons[i].tabIndex === 0) {
555
+ current = i;
556
+ break;
443
557
  }
558
+ }
559
+ if (current < 0) return;
560
+ const next = (current + direction + buttons.length) % buttons.length;
561
+ buttons[current].tabIndex = -1;
562
+ buttons[next].tabIndex = 0;
563
+ buttons[next].focus();
564
+ }
565
+
566
+ function ExpandableContainer({
567
+ field,
568
+ entries,
569
+ open,
570
+ close,
571
+ prefix,
572
+ ctx,
573
+ isLast,
574
+ }: {
575
+ field?: string;
576
+ entries: Entry[];
577
+ open: string;
578
+ close: string;
579
+ prefix?: string;
580
+ ctx: NodeContext;
581
+ isLast: boolean;
582
+ }) {
583
+ const { level, shouldExpand, outerRef } = ctx;
584
+ const [expanded, setExpanded] = useState(() => shouldExpand(level));
585
+ const rowRef = useRef<HTMLDivElement>(null);
586
+ const contentsId = useId();
587
+
588
+ if (entries.length === 0) {
444
589
  return (
445
- <span>
446
- {name != null && <ObjectName name={name} />}
447
- {name != null && <span>: </span>}
448
- {label}
449
- </span>
590
+ <EmptyContainer
591
+ field={field}
592
+ prefix={prefix}
593
+ open={open}
594
+ close={close}
595
+ isLast={isLast}
596
+ />
450
597
  );
451
598
  }
452
599
 
453
- // StreamRef inline clickable badge
454
- if (isStreamRef(data)) {
600
+ const toggle = () => {
601
+ setExpanded((value) => !value);
602
+ if (rowRef.current) focusExpander(rowRef.current, outerRef);
603
+ };
604
+
605
+ // Toggle only for clicks that land on this row itself; clicks bubbling up out
606
+ // of a nested treeitem are handled by that descendant's own row.
607
+ const onClick = (event: ReactMouseEvent) => {
608
+ if (
609
+ (event.target as HTMLElement).closest('[role="treeitem"]') !==
610
+ event.currentTarget
611
+ ) {
612
+ return;
613
+ }
614
+ toggle();
615
+ };
616
+
617
+ const onKeyDown = (event: ReactKeyboardEvent) => {
618
+ if (event.key === 'ArrowRight') {
619
+ event.preventDefault();
620
+ setExpanded(true);
621
+ } else if (event.key === 'ArrowLeft') {
622
+ event.preventDefault();
623
+ setExpanded(false);
624
+ } else if (event.key === 'ArrowUp') {
625
+ event.preventDefault();
626
+ moveExpanderFocus(outerRef, -1);
627
+ } else if (event.key === 'ArrowDown') {
628
+ event.preventDefault();
629
+ moveExpanderFocus(outerRef, 1);
630
+ }
631
+ };
632
+
633
+ const lastIndex = entries.length - 1;
634
+
635
+ return (
636
+ // The treeitem row is the focusable, keyboard-operable control (roving
637
+ // tabindex + arrow keys); the disclosure marker below is purely decorative.
638
+ <div
639
+ className={CLS.child}
640
+ role="treeitem"
641
+ aria-expanded={expanded}
642
+ aria-controls={expanded ? contentsId : undefined}
643
+ data-json-expander
644
+ ref={rowRef}
645
+ tabIndex={level === 0 ? 0 : -1}
646
+ onClick={onClick}
647
+ onKeyDown={onKeyDown}
648
+ >
649
+ <span
650
+ className={expanded ? CLS.collapseIcon : CLS.expandIcon}
651
+ aria-hidden="true"
652
+ />
653
+ {field !== undefined && (
654
+ <span className={CLS.clickableLabel}>{`${formatField(field)}:`}</span>
655
+ )}
656
+ {prefix ? <span className={CLS.className}>{prefix}</span> : null}
657
+ <span className={CLS.punctuation}>{open}</span>
658
+ {expanded ? (
659
+ // biome-ignore lint/a11y/useSemanticElements: ARIA tree group is the correct role here
660
+ <ul id={contentsId} className={CLS.childFields} role="group">
661
+ {entries.map(([childField, childValue], index) => (
662
+ <DataRender
663
+ key={childField ?? index}
664
+ field={childField}
665
+ value={childValue}
666
+ isLast={index === lastIndex}
667
+ ctx={{ ...ctx, level: level + 1 }}
668
+ />
669
+ ))}
670
+ </ul>
671
+ ) : (
672
+ <span className={CLS.collapsedContent} aria-hidden="true" />
673
+ )}
674
+ <span className={CLS.punctuation}>{close}</span>
675
+ <Comma isLast={isLast} />
676
+ </div>
677
+ );
678
+ }
679
+
680
+ interface NodeProps {
681
+ field?: string;
682
+ value: unknown;
683
+ isLast: boolean;
684
+ ctx: NodeContext;
685
+ }
686
+
687
+ function DataRender({ field, value, isLast, ctx }: NodeProps) {
688
+ if (isBytesDisplay(value)) {
455
689
  return (
456
- <span>
457
- {name != null && <ObjectName name={name} />}
458
- {name != null && <span>: </span>}
459
- <StreamRefInline streamRef={data} />
460
- </span>
690
+ <LeafRow field={field} isLast={isLast}>
691
+ <BytesDisplayValue display={value} />
692
+ </LeafRow>
461
693
  );
462
694
  }
463
-
464
- // RunRef → inline clickable badge linking to the target run
465
- if (isRunRef(data)) {
695
+ if (isEncryptedMarker(value)) {
466
696
  return (
467
- <span>
468
- {name != null && <ObjectName name={name} />}
469
- {name != null && <span>: </span>}
470
- <RunRefInline runRef={data} />
471
- </span>
697
+ <LeafRow field={field} isLast={isLast}>
698
+ <EncryptedInlineLabel />
699
+ </LeafRow>
472
700
  );
473
701
  }
474
-
475
- // ClassInstanceRef → show className as type, data as the inspectable value
476
- if (isClassInstanceRef(data)) {
477
- if (depth === 0) {
478
- return <ObjectRootLabel name={data.className} data={data.data} />;
479
- }
702
+ if (isStreamRef(value)) {
703
+ return (
704
+ <LeafRow field={field} isLast={isLast}>
705
+ <StreamRefInline streamRef={value} />
706
+ </LeafRow>
707
+ );
708
+ }
709
+ if (isRunRef(value)) {
710
+ return (
711
+ <LeafRow field={field} isLast={isLast}>
712
+ <RunRefInline runRef={value} />
713
+ </LeafRow>
714
+ );
715
+ }
716
+ if (value instanceof Date) {
717
+ return (
718
+ <LeafRow field={field} isLast={isLast}>
719
+ <span className={CLS.date}>{value.toISOString()}</span>
720
+ </LeafRow>
721
+ );
722
+ }
723
+ if (value instanceof RegExp) {
724
+ return (
725
+ <LeafRow field={field} isLast={isLast}>
726
+ <span className={CLS.regexp}>{value.toString()}</span>
727
+ </LeafRow>
728
+ );
729
+ }
730
+ if (isClassInstanceRef(value)) {
480
731
  return (
481
- <span>
482
- {name != null && <ObjectName name={name} />}
483
- {name != null && <span>: </span>}
484
- <span style={{ fontStyle: 'italic' }}>{data.className} </span>
485
- <ObjectValue object={data.data} />
486
- </span>
732
+ <ClassInstanceNode
733
+ field={field}
734
+ instance={value}
735
+ isLast={isLast}
736
+ ctx={ctx}
737
+ />
487
738
  );
488
739
  }
489
740
 
490
- // Date magenta color (Node.js: 'date' → 'magenta')
491
- // react-inspector has no OBJECT_VALUE_DATE_COLOR theme key, so we handle it here.
492
- if (data instanceof Date) {
493
- const dateStr = data.toISOString();
494
- if (depth === 0) {
495
- return (
496
- <span style={{ color: extendedTheme.OBJECT_VALUE_DATE_COLOR }}>
497
- {dateStr}
498
- </span>
499
- );
500
- }
741
+ const container = describeContainer(value);
742
+ if (container) {
501
743
  return (
502
- <span>
503
- {name != null && <ObjectName name={name} />}
504
- {name != null && <span>: </span>}
505
- <span style={{ color: extendedTheme.OBJECT_VALUE_DATE_COLOR }}>
506
- {dateStr}
507
- </span>
508
- </span>
744
+ <ExpandableContainer
745
+ field={field}
746
+ entries={container.entries}
747
+ open={container.open}
748
+ close={container.close}
749
+ prefix={container.prefix}
750
+ ctx={ctx}
751
+ isLast={isLast}
752
+ />
509
753
  );
510
754
  }
511
755
 
512
- // Default rendering (same as react-inspector's built-in)
513
- if (depth === 0) {
514
- return <ObjectRootLabel name={name} data={data} />;
756
+ return (
757
+ <PrimitiveValue field={field} value={value} isLast={isLast} ctx={ctx} />
758
+ );
759
+ }
760
+
761
+ function ClassInstanceNode({
762
+ field,
763
+ instance,
764
+ isLast,
765
+ ctx,
766
+ }: {
767
+ field?: string;
768
+ instance: ClassInstanceRef;
769
+ isLast: boolean;
770
+ ctx: NodeContext;
771
+ }) {
772
+ const container = describeContainer(instance.data);
773
+ if (container) {
774
+ return (
775
+ <ExpandableContainer
776
+ field={field}
777
+ entries={container.entries}
778
+ open={container.open}
779
+ close={container.close}
780
+ prefix={instance.className}
781
+ ctx={ctx}
782
+ isLast={isLast}
783
+ />
784
+ );
515
785
  }
786
+ const { text, cls } = describePrimitive(instance.data);
516
787
  return (
517
- <ObjectLabel name={name} data={data} isNonenumerable={isNonenumerable} />
788
+ <LeafRow field={field} isLast={isLast}>
789
+ <span className={CLS.className}>{instance.className}</span>
790
+ <span className={cls}>{text}</span>
791
+ </LeafRow>
792
+ );
793
+ }
794
+
795
+ function JsonTree({
796
+ data,
797
+ name,
798
+ expandLevel,
799
+ }: {
800
+ data: unknown;
801
+ name?: string;
802
+ expandLevel: number;
803
+ }) {
804
+ const outerRef = useRef<HTMLDivElement>(null);
805
+ const shouldExpand = useMemo(
806
+ () => (level: number) => level < expandLevel,
807
+ [expandLevel]
808
+ );
809
+ return (
810
+ <div
811
+ ref={outerRef}
812
+ className={CLS.container}
813
+ role="tree"
814
+ aria-label="JSON view"
815
+ >
816
+ <DataRender
817
+ field={name}
818
+ value={data}
819
+ isLast
820
+ ctx={{ level: 0, shouldExpand, outerRef }}
821
+ />
822
+ </div>
518
823
  );
519
824
  }
520
825
 
521
826
  // ---------------------------------------------------------------------------
522
- // Public component
827
+ // Ref / typed-array collapsing (preprocessing before render)
523
828
  // ---------------------------------------------------------------------------
524
829
 
525
830
  /**
526
831
  * Create a non-expandable wrapper that carries ref data as non-enumerable
527
- * properties. ObjectInspector won't render children for objects with no
528
- * enumerable keys, but our NodeRenderer can still detect them.
832
+ * properties so the renderer can detect StreamRef/RunRef without exposing
833
+ * their internals as object fields.
529
834
  */
530
835
  function makeOpaqueRef(ref: Record<string, unknown>): unknown {
531
836
  const opaque = Object.create(null);
@@ -554,11 +859,11 @@ function makeBytesDisplay(display: FormattedStreamChunkDisplay): unknown {
554
859
 
555
860
  /**
556
861
  * Recursively walk data and replace RunRef/StreamRef/typed array objects with
557
- * non-expandable versions so ObjectInspector doesn't show their internals.
862
+ * non-expandable versions so the renderer doesn't show their internals.
558
863
  * Only recurses into plain objects and arrays to avoid stripping class
559
- * instances (Date, Error, URL, Headers, etc.) that have their own rendering in
560
- * NodeRenderer. Map and Set containers are preserved while their contents are
561
- * prepared for display.
864
+ * instances (Date, Error, URL, Headers, etc.) that have their own rendering.
865
+ * Map and Set containers are preserved while their contents are prepared for
866
+ * display.
562
867
  *
563
868
  * Exported for testing the typed-array detection path used by hydrated
564
869
  * AI agent stream chunks (e.g. `{ delta: new Uint8Array(...) }`).
@@ -592,10 +897,14 @@ export function collapseRefs(data: unknown): unknown {
592
897
  return result;
593
898
  }
594
899
 
900
+ // ---------------------------------------------------------------------------
901
+ // Public component
902
+ // ---------------------------------------------------------------------------
903
+
595
904
  export interface DataInspectorProps {
596
905
  /** The data to inspect */
597
906
  data: unknown;
598
- /** Initial expand depth (default: 2) */
907
+ /** Levels strictly below this number auto-expand (default: 2) */
599
908
  expandLevel?: number;
600
909
  /** Optional name for the root node */
601
910
  name?: string;
@@ -620,59 +929,47 @@ export function DataInspector({
620
929
  }: DataInspectorProps) {
621
930
  const collapsedData = useMemo(() => collapseRefs(data), [data]);
622
931
  const stableData = useStableInspectorData(collapsedData);
623
- const [initialExpandLevel, setInitialExpandLevel] = useState(expandLevel);
624
- const isDark = useDarkMode();
625
- const extendedTheme = isDark
626
- ? inspectorThemeExtendedDark
627
- : inspectorThemeExtendedLight;
628
-
629
- useEffect(() => {
630
- // react-inspector reapplies expandLevel on every data change, which can
631
- // reopen paths the user manually collapsed. Apply it only on mount.
632
- setInitialExpandLevel(0);
633
- }, []);
634
-
635
- const content = (
636
- <ExtendedThemeContext.Provider value={extendedTheme}>
637
- <ObjectInspector
638
- data={stableData}
639
- name={name}
640
- // @ts-expect-error react-inspector accepts theme objects at runtime despite
641
- // types declaring string only — see https://github.com/storybookjs/react-inspector/blob/main/README.md#theme
642
- theme={isDark ? inspectorThemeDark : inspectorThemeLight}
643
- expandLevel={initialExpandLevel}
644
- nodeRenderer={NodeRenderer}
645
- />
646
- </ExtendedThemeContext.Provider>
647
- );
648
932
 
649
- let wrapped = content;
933
+ let content: ReactNode = (
934
+ <>
935
+ {/* React 19 hoists & dedupes this <style> by href, so it is emitted once
936
+ regardless of how many inspectors are mounted. */}
937
+ <style href="wf-json-view" precedence="default">
938
+ {JSON_VIEW_STYLES}
939
+ </style>
940
+ <JsonTree data={stableData} name={name} expandLevel={expandLevel} />
941
+ </>
942
+ );
650
943
 
651
944
  if (onStreamClick) {
652
- wrapped = (
945
+ content = (
653
946
  <StreamClickContext.Provider value={onStreamClick}>
654
- {wrapped}
947
+ {content}
655
948
  </StreamClickContext.Provider>
656
949
  );
657
950
  }
658
951
  if (onRunClick) {
659
- wrapped = (
952
+ content = (
660
953
  <RunClickContext.Provider value={onRunClick}>
661
- {wrapped}
954
+ {content}
662
955
  </RunClickContext.Provider>
663
956
  );
664
957
  }
665
958
  if (onDecrypt) {
666
- wrapped = (
959
+ content = (
667
960
  <DecryptClickContext.Provider value={{ onDecrypt, isDecrypting }}>
668
- {wrapped}
961
+ {content}
669
962
  </DecryptClickContext.Provider>
670
963
  );
671
964
  }
672
965
 
673
- return wrapped;
966
+ return content;
674
967
  }
675
968
 
969
+ // ---------------------------------------------------------------------------
970
+ // Render stabilization (avoid re-renders when data is deeply equal)
971
+ // ---------------------------------------------------------------------------
972
+
676
973
  function useStableInspectorData<T>(next: T): T {
677
974
  const previousRef = useRef<T>(next);
678
975
  if (!isDeepEqual(previousRef.current, next)) {