@flanksource/clicky-ui 0.3.45 → 0.3.47

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 (505) hide show
  1. package/NOTICE.md +11 -0
  2. package/README.md +22 -0
  3. package/dist/ai.cjs +13 -8
  4. package/dist/ai.cjs.map +1 -1
  5. package/dist/ai.js +7 -2
  6. package/dist/ai.js.map +1 -1
  7. package/dist/components/ErrorWrapper.cjs +2 -3
  8. package/dist/components/ErrorWrapper.cjs.map +1 -1
  9. package/dist/components/ErrorWrapper.d.ts.map +1 -1
  10. package/dist/components/ErrorWrapper.js +3 -4
  11. package/dist/components/ErrorWrapper.js.map +1 -1
  12. package/dist/data/AccessMark.cjs +23 -0
  13. package/dist/data/AccessMark.cjs.map +1 -0
  14. package/dist/data/AccessMark.d.ts +11 -0
  15. package/dist/data/AccessMark.d.ts.map +1 -0
  16. package/dist/data/AccessMark.js +23 -0
  17. package/dist/data/AccessMark.js.map +1 -0
  18. package/dist/data/Clicky.cjs +3 -0
  19. package/dist/data/Clicky.cjs.map +1 -1
  20. package/dist/data/Clicky.js +3 -0
  21. package/dist/data/Clicky.js.map +1 -1
  22. package/dist/data/CodeDiff.cjs +116 -23
  23. package/dist/data/CodeDiff.cjs.map +1 -1
  24. package/dist/data/CodeDiff.d.ts +26 -0
  25. package/dist/data/CodeDiff.d.ts.map +1 -1
  26. package/dist/data/CodeDiff.js +116 -23
  27. package/dist/data/CodeDiff.js.map +1 -1
  28. package/dist/data/FilterPill.cjs +15 -2
  29. package/dist/data/FilterPill.cjs.map +1 -1
  30. package/dist/data/FilterPill.d.ts +1 -1
  31. package/dist/data/FilterPill.d.ts.map +1 -1
  32. package/dist/data/FilterPill.js +15 -2
  33. package/dist/data/FilterPill.js.map +1 -1
  34. package/dist/data/GraphDiagram.cjs +65 -13
  35. package/dist/data/GraphDiagram.cjs.map +1 -1
  36. package/dist/data/GraphDiagram.d.ts +9 -2
  37. package/dist/data/GraphDiagram.d.ts.map +1 -1
  38. package/dist/data/GraphDiagram.js +66 -14
  39. package/dist/data/GraphDiagram.js.map +1 -1
  40. package/dist/data/GraphDiagramGroups.cjs +100 -0
  41. package/dist/data/GraphDiagramGroups.cjs.map +1 -0
  42. package/dist/data/GraphDiagramGroups.d.ts +24 -0
  43. package/dist/data/GraphDiagramGroups.d.ts.map +1 -0
  44. package/dist/data/GraphDiagramGroups.js +100 -0
  45. package/dist/data/GraphDiagramGroups.js.map +1 -0
  46. package/dist/data/GraphDiagramNodes.cjs +17 -31
  47. package/dist/data/GraphDiagramNodes.cjs.map +1 -1
  48. package/dist/data/GraphDiagramNodes.d.ts +6 -13
  49. package/dist/data/GraphDiagramNodes.d.ts.map +1 -1
  50. package/dist/data/GraphDiagramNodes.js +17 -31
  51. package/dist/data/GraphDiagramNodes.js.map +1 -1
  52. package/dist/data/LogViewer.cjs +27 -8
  53. package/dist/data/LogViewer.cjs.map +1 -1
  54. package/dist/data/LogViewer.d.ts +11 -3
  55. package/dist/data/LogViewer.d.ts.map +1 -1
  56. package/dist/data/LogViewer.js +27 -8
  57. package/dist/data/LogViewer.js.map +1 -1
  58. package/dist/data/Properties.cjs +2 -15
  59. package/dist/data/Properties.cjs.map +1 -1
  60. package/dist/data/Properties.d.ts +4 -0
  61. package/dist/data/Properties.d.ts.map +1 -1
  62. package/dist/data/Properties.js +2 -15
  63. package/dist/data/Properties.js.map +1 -1
  64. package/dist/data/PropertyValue.cjs +37 -0
  65. package/dist/data/PropertyValue.cjs.map +1 -0
  66. package/dist/data/PropertyValue.d.ts +6 -0
  67. package/dist/data/PropertyValue.d.ts.map +1 -0
  68. package/dist/data/PropertyValue.js +37 -0
  69. package/dist/data/PropertyValue.js.map +1 -0
  70. package/dist/data/Tree.cjs +4 -3
  71. package/dist/data/Tree.cjs.map +1 -1
  72. package/dist/data/Tree.d.ts +3 -1
  73. package/dist/data/Tree.d.ts.map +1 -1
  74. package/dist/data/Tree.js +4 -3
  75. package/dist/data/Tree.js.map +1 -1
  76. package/dist/data/TreeNode.cjs +1 -1
  77. package/dist/data/TreeNode.cjs.map +1 -1
  78. package/dist/data/TreeNode.d.ts.map +1 -1
  79. package/dist/data/TreeNode.js +1 -1
  80. package/dist/data/TreeNode.js.map +1 -1
  81. package/dist/data/ai/ChatFab.cjs +1 -1
  82. package/dist/data/ai/ChatFab.cjs.map +1 -1
  83. package/dist/data/ai/ChatFab.js +1 -1
  84. package/dist/data/ai/ChatFab.js.map +1 -1
  85. package/dist/data/ai/ChatWindow.cjs +106 -171
  86. package/dist/data/ai/ChatWindow.cjs.map +1 -1
  87. package/dist/data/ai/ChatWindow.d.ts +6 -2
  88. package/dist/data/ai/ChatWindow.d.ts.map +1 -1
  89. package/dist/data/ai/ChatWindow.header.cjs +104 -0
  90. package/dist/data/ai/ChatWindow.header.cjs.map +1 -0
  91. package/dist/data/ai/ChatWindow.header.d.ts +29 -0
  92. package/dist/data/ai/ChatWindow.header.d.ts.map +1 -0
  93. package/dist/data/ai/ChatWindow.header.js +104 -0
  94. package/dist/data/ai/ChatWindow.header.js.map +1 -0
  95. package/dist/data/ai/ChatWindow.js +107 -172
  96. package/dist/data/ai/ChatWindow.js.map +1 -1
  97. package/dist/data/ai/ChatWindow.placement.cjs +95 -0
  98. package/dist/data/ai/ChatWindow.placement.cjs.map +1 -0
  99. package/dist/data/ai/ChatWindow.placement.d.ts +32 -0
  100. package/dist/data/ai/ChatWindow.placement.d.ts.map +1 -0
  101. package/dist/data/ai/ChatWindow.placement.js +95 -0
  102. package/dist/data/ai/ChatWindow.placement.js.map +1 -0
  103. package/dist/data/ai/SessionChatComposer.cjs +3 -1
  104. package/dist/data/ai/SessionChatComposer.cjs.map +1 -1
  105. package/dist/data/ai/SessionChatComposer.d.ts +4 -1
  106. package/dist/data/ai/SessionChatComposer.d.ts.map +1 -1
  107. package/dist/data/ai/SessionChatComposer.js +3 -1
  108. package/dist/data/ai/SessionChatComposer.js.map +1 -1
  109. package/dist/data/ai/SessionInspector.cjs +68 -72
  110. package/dist/data/ai/SessionInspector.cjs.map +1 -1
  111. package/dist/data/ai/SessionInspector.composer-slot.cjs +8 -0
  112. package/dist/data/ai/SessionInspector.composer-slot.cjs.map +1 -0
  113. package/dist/data/ai/SessionInspector.composer-slot.d.ts +9 -0
  114. package/dist/data/ai/SessionInspector.composer-slot.d.ts.map +1 -0
  115. package/dist/data/ai/SessionInspector.composer-slot.js +8 -0
  116. package/dist/data/ai/SessionInspector.composer-slot.js.map +1 -0
  117. package/dist/data/ai/SessionInspector.d.ts +6 -1
  118. package/dist/data/ai/SessionInspector.d.ts.map +1 -1
  119. package/dist/data/ai/SessionInspector.js +69 -73
  120. package/dist/data/ai/SessionInspector.js.map +1 -1
  121. package/dist/data/ai/SessionInspector.legacy.cjs +41 -42
  122. package/dist/data/ai/SessionInspector.legacy.cjs.map +1 -1
  123. package/dist/data/ai/SessionInspector.legacy.d.ts.map +1 -1
  124. package/dist/data/ai/SessionInspector.legacy.js +41 -42
  125. package/dist/data/ai/SessionInspector.legacy.js.map +1 -1
  126. package/dist/data/ai/SessionInspector.remote-view.cjs +14 -9
  127. package/dist/data/ai/SessionInspector.remote-view.cjs.map +1 -1
  128. package/dist/data/ai/SessionInspector.remote-view.d.ts +6 -2
  129. package/dist/data/ai/SessionInspector.remote-view.d.ts.map +1 -1
  130. package/dist/data/ai/SessionInspector.remote-view.js +14 -9
  131. package/dist/data/ai/SessionInspector.remote-view.js.map +1 -1
  132. package/dist/data/ai/SessionInspector.remote.cjs +84 -16
  133. package/dist/data/ai/SessionInspector.remote.cjs.map +1 -1
  134. package/dist/data/ai/SessionInspector.remote.d.ts +42 -7
  135. package/dist/data/ai/SessionInspector.remote.d.ts.map +1 -1
  136. package/dist/data/ai/SessionInspector.remote.js +86 -18
  137. package/dist/data/ai/SessionInspector.remote.js.map +1 -1
  138. package/dist/data/ai/SessionInspector.transcript.cjs +5 -0
  139. package/dist/data/ai/SessionInspector.transcript.cjs.map +1 -1
  140. package/dist/data/ai/SessionInspector.transcript.d.ts.map +1 -1
  141. package/dist/data/ai/SessionInspector.transcript.js +5 -0
  142. package/dist/data/ai/SessionInspector.transcript.js.map +1 -1
  143. package/dist/data/ai/SessionTail.cjs +63 -0
  144. package/dist/data/ai/SessionTail.cjs.map +1 -0
  145. package/dist/data/ai/SessionTail.d.ts +14 -0
  146. package/dist/data/ai/SessionTail.d.ts.map +1 -0
  147. package/dist/data/ai/SessionTail.js +63 -0
  148. package/dist/data/ai/SessionTail.js.map +1 -0
  149. package/dist/data/ai/SessionViewer.cjs +10 -3
  150. package/dist/data/ai/SessionViewer.cjs.map +1 -1
  151. package/dist/data/ai/SessionViewer.d.ts +7 -1
  152. package/dist/data/ai/SessionViewer.d.ts.map +1 -1
  153. package/dist/data/ai/SessionViewer.js +10 -3
  154. package/dist/data/ai/SessionViewer.js.map +1 -1
  155. package/dist/data/ai/SessionViewer.unified.d.ts +14 -0
  156. package/dist/data/ai/SessionViewer.unified.d.ts.map +1 -1
  157. package/dist/data/ai/index.d.ts +4 -3
  158. package/dist/data/ai/index.d.ts.map +1 -1
  159. package/dist/data/ai/use-session-scroll.cjs +30 -6
  160. package/dist/data/ai/use-session-scroll.cjs.map +1 -1
  161. package/dist/data/ai/use-session-scroll.d.ts +7 -0
  162. package/dist/data/ai/use-session-scroll.d.ts.map +1 -1
  163. package/dist/data/ai/use-session-scroll.js +30 -6
  164. package/dist/data/ai/use-session-scroll.js.map +1 -1
  165. package/dist/data/call-graph/CallGraph.cjs +50 -31
  166. package/dist/data/call-graph/CallGraph.cjs.map +1 -1
  167. package/dist/data/call-graph/CallGraph.d.ts +10 -1
  168. package/dist/data/call-graph/CallGraph.d.ts.map +1 -1
  169. package/dist/data/call-graph/CallGraph.js +52 -33
  170. package/dist/data/call-graph/CallGraph.js.map +1 -1
  171. package/dist/data/call-graph/CallGraphMembers.cjs +5 -4
  172. package/dist/data/call-graph/CallGraphMembers.cjs.map +1 -1
  173. package/dist/data/call-graph/CallGraphMembers.d.ts +1 -1
  174. package/dist/data/call-graph/CallGraphMembers.d.ts.map +1 -1
  175. package/dist/data/call-graph/CallGraphMembers.js +5 -4
  176. package/dist/data/call-graph/CallGraphMembers.js.map +1 -1
  177. package/dist/data/call-graph/CallGraphToolbar.cjs +17 -5
  178. package/dist/data/call-graph/CallGraphToolbar.cjs.map +1 -1
  179. package/dist/data/call-graph/CallGraphToolbar.d.ts +10 -0
  180. package/dist/data/call-graph/CallGraphToolbar.d.ts.map +1 -1
  181. package/dist/data/call-graph/CallGraphToolbar.js +18 -6
  182. package/dist/data/call-graph/CallGraphToolbar.js.map +1 -1
  183. package/dist/data/call-graph/call-graph-model.cjs +169 -18
  184. package/dist/data/call-graph/call-graph-model.cjs.map +1 -1
  185. package/dist/data/call-graph/call-graph-model.d.ts +40 -4
  186. package/dist/data/call-graph/call-graph-model.d.ts.map +1 -1
  187. package/dist/data/call-graph/call-graph-model.js +170 -19
  188. package/dist/data/call-graph/call-graph-model.js.map +1 -1
  189. package/dist/data/call-graph/call-graph-vocabulary.cjs +19 -1
  190. package/dist/data/call-graph/call-graph-vocabulary.cjs.map +1 -1
  191. package/dist/data/call-graph/call-graph-vocabulary.d.ts +4 -0
  192. package/dist/data/call-graph/call-graph-vocabulary.d.ts.map +1 -1
  193. package/dist/data/call-graph/call-graph-vocabulary.js +19 -1
  194. package/dist/data/call-graph/call-graph-vocabulary.js.map +1 -1
  195. package/dist/data/call-graph/call-graph.fixtures.d.ts.map +1 -1
  196. package/dist/data/call-graph/index.d.ts +2 -2
  197. package/dist/data/call-graph/index.d.ts.map +1 -1
  198. package/dist/data/call-graph/types.cjs.map +1 -1
  199. package/dist/data/call-graph/types.d.ts +7 -2
  200. package/dist/data/call-graph/types.d.ts.map +1 -1
  201. package/dist/data/call-graph/types.js.map +1 -1
  202. package/dist/data/chat/Chat.cjs +1 -1
  203. package/dist/data/chat/Chat.cjs.map +1 -1
  204. package/dist/data/chat/Chat.js +1 -1
  205. package/dist/data/chat/Chat.js.map +1 -1
  206. package/dist/data/chat/ChatRuntimeToolbar.cjs +4 -4
  207. package/dist/data/chat/ChatRuntimeToolbar.cjs.map +1 -1
  208. package/dist/data/chat/ChatRuntimeToolbar.d.ts.map +1 -1
  209. package/dist/data/chat/ChatRuntimeToolbar.js +4 -4
  210. package/dist/data/chat/ChatRuntimeToolbar.js.map +1 -1
  211. package/dist/data/chat/PromptInput.cjs +4 -2
  212. package/dist/data/chat/PromptInput.cjs.map +1 -1
  213. package/dist/data/chat/PromptInput.d.ts +5 -1
  214. package/dist/data/chat/PromptInput.d.ts.map +1 -1
  215. package/dist/data/chat/PromptInput.js +4 -2
  216. package/dist/data/chat/PromptInput.js.map +1 -1
  217. package/dist/data/data-access.cjs +8 -0
  218. package/dist/data/data-access.cjs.map +1 -0
  219. package/dist/data/data-access.d.ts +5 -0
  220. package/dist/data/data-access.d.ts.map +1 -0
  221. package/dist/data/data-access.js +8 -0
  222. package/dist/data/data-access.js.map +1 -0
  223. package/dist/data/diagnostics/ErrorDetails.cjs +13 -2
  224. package/dist/data/diagnostics/ErrorDetails.cjs.map +1 -1
  225. package/dist/data/diagnostics/ErrorDetails.d.ts +3 -1
  226. package/dist/data/diagnostics/ErrorDetails.d.ts.map +1 -1
  227. package/dist/data/diagnostics/ErrorDetails.js +14 -3
  228. package/dist/data/diagnostics/ErrorDetails.js.map +1 -1
  229. package/dist/data/diagnostics/FrameSourceWindow.cjs +3 -2
  230. package/dist/data/diagnostics/FrameSourceWindow.cjs.map +1 -1
  231. package/dist/data/diagnostics/FrameSourceWindow.d.ts.map +1 -1
  232. package/dist/data/diagnostics/FrameSourceWindow.js +3 -2
  233. package/dist/data/diagnostics/FrameSourceWindow.js.map +1 -1
  234. package/dist/data/diagnostics/error-diagnostics.cjs +5 -0
  235. package/dist/data/diagnostics/error-diagnostics.cjs.map +1 -1
  236. package/dist/data/diagnostics/error-diagnostics.d.ts +1 -0
  237. package/dist/data/diagnostics/error-diagnostics.d.ts.map +1 -1
  238. package/dist/data/diagnostics/error-diagnostics.js +6 -1
  239. package/dist/data/diagnostics/error-diagnostics.js.map +1 -1
  240. package/dist/data/git/GitChangeList.cjs +6 -2
  241. package/dist/data/git/GitChangeList.cjs.map +1 -1
  242. package/dist/data/git/GitChangeList.d.ts +6 -1
  243. package/dist/data/git/GitChangeList.d.ts.map +1 -1
  244. package/dist/data/git/GitChangeList.js +6 -2
  245. package/dist/data/git/GitChangeList.js.map +1 -1
  246. package/dist/data/graph-columns-layout.cjs +47 -16
  247. package/dist/data/graph-columns-layout.cjs.map +1 -1
  248. package/dist/data/graph-columns-layout.d.ts +34 -0
  249. package/dist/data/graph-columns-layout.d.ts.map +1 -1
  250. package/dist/data/graph-columns-layout.js +47 -16
  251. package/dist/data/graph-columns-layout.js.map +1 -1
  252. package/dist/data/graph-diagram-model.cjs +5 -0
  253. package/dist/data/graph-diagram-model.cjs.map +1 -1
  254. package/dist/data/graph-diagram-model.d.ts +19 -0
  255. package/dist/data/graph-diagram-model.d.ts.map +1 -1
  256. package/dist/data/graph-diagram-model.js +5 -0
  257. package/dist/data/graph-diagram-model.js.map +1 -1
  258. package/dist/data/graph-group-window.cjs +60 -0
  259. package/dist/data/graph-group-window.cjs.map +1 -0
  260. package/dist/data/graph-group-window.d.ts +33 -0
  261. package/dist/data/graph-group-window.d.ts.map +1 -0
  262. package/dist/data/graph-group-window.js +60 -0
  263. package/dist/data/graph-group-window.js.map +1 -0
  264. package/dist/data/har/HarPanel.cjs +3 -1
  265. package/dist/data/har/HarPanel.cjs.map +1 -1
  266. package/dist/data/har/HarPanel.d.ts +4 -1
  267. package/dist/data/har/HarPanel.d.ts.map +1 -1
  268. package/dist/data/har/HarPanel.js +3 -1
  269. package/dist/data/har/HarPanel.js.map +1 -1
  270. package/dist/data/test-runner/Expectation.cjs +57 -0
  271. package/dist/data/test-runner/Expectation.cjs.map +1 -0
  272. package/dist/data/test-runner/Expectation.d.ts +19 -0
  273. package/dist/data/test-runner/Expectation.d.ts.map +1 -0
  274. package/dist/data/test-runner/Expectation.js +57 -0
  275. package/dist/data/test-runner/Expectation.js.map +1 -0
  276. package/dist/data/test-runner/MarkIcons.cjs +38 -0
  277. package/dist/data/test-runner/MarkIcons.cjs.map +1 -0
  278. package/dist/data/test-runner/MarkIcons.d.ts +15 -0
  279. package/dist/data/test-runner/MarkIcons.d.ts.map +1 -0
  280. package/dist/data/test-runner/MarkIcons.js +38 -0
  281. package/dist/data/test-runner/MarkIcons.js.map +1 -0
  282. package/dist/data/test-runner/TestDetailPanel.cjs +74 -42
  283. package/dist/data/test-runner/TestDetailPanel.cjs.map +1 -1
  284. package/dist/data/test-runner/TestDetailPanel.d.ts.map +1 -1
  285. package/dist/data/test-runner/TestDetailPanel.js +76 -44
  286. package/dist/data/test-runner/TestDetailPanel.js.map +1 -1
  287. package/dist/data/test-runner/TestFailureDetail.cjs +23 -27
  288. package/dist/data/test-runner/TestFailureDetail.cjs.map +1 -1
  289. package/dist/data/test-runner/TestFailureDetail.d.ts +2 -2
  290. package/dist/data/test-runner/TestFailureDetail.d.ts.map +1 -1
  291. package/dist/data/test-runner/TestFailureDetail.js +23 -27
  292. package/dist/data/test-runner/TestFailureDetail.js.map +1 -1
  293. package/dist/data/test-runner/TestFilterBar.cjs +87 -93
  294. package/dist/data/test-runner/TestFilterBar.cjs.map +1 -1
  295. package/dist/data/test-runner/TestFilterBar.d.ts +3 -2
  296. package/dist/data/test-runner/TestFilterBar.d.ts.map +1 -1
  297. package/dist/data/test-runner/TestFilterBar.js +89 -95
  298. package/dist/data/test-runner/TestFilterBar.js.map +1 -1
  299. package/dist/data/test-runner/TestRunSummary.cjs +35 -21
  300. package/dist/data/test-runner/TestRunSummary.cjs.map +1 -1
  301. package/dist/data/test-runner/TestRunSummary.d.ts.map +1 -1
  302. package/dist/data/test-runner/TestRunSummary.js +35 -21
  303. package/dist/data/test-runner/TestRunSummary.js.map +1 -1
  304. package/dist/data/test-runner/TestRunner.cjs +52 -30
  305. package/dist/data/test-runner/TestRunner.cjs.map +1 -1
  306. package/dist/data/test-runner/TestRunner.d.ts +3 -2
  307. package/dist/data/test-runner/TestRunner.d.ts.map +1 -1
  308. package/dist/data/test-runner/TestRunner.js +52 -30
  309. package/dist/data/test-runner/TestRunner.js.map +1 -1
  310. package/dist/data/test-runner/TestTree.cjs +5 -2
  311. package/dist/data/test-runner/TestTree.cjs.map +1 -1
  312. package/dist/data/test-runner/TestTree.d.ts +5 -2
  313. package/dist/data/test-runner/TestTree.d.ts.map +1 -1
  314. package/dist/data/test-runner/TestTree.js +5 -2
  315. package/dist/data/test-runner/TestTree.js.map +1 -1
  316. package/dist/data/test-runner/TestTreeNode.cjs +27 -19
  317. package/dist/data/test-runner/TestTreeNode.cjs.map +1 -1
  318. package/dist/data/test-runner/TestTreeNode.d.ts.map +1 -1
  319. package/dist/data/test-runner/TestTreeNode.js +28 -20
  320. package/dist/data/test-runner/TestTreeNode.js.map +1 -1
  321. package/dist/data/test-runner/adapter.cjs +11 -0
  322. package/dist/data/test-runner/adapter.cjs.map +1 -1
  323. package/dist/data/test-runner/adapter.d.ts +18 -7
  324. package/dist/data/test-runner/adapter.d.ts.map +1 -1
  325. package/dist/data/test-runner/adapter.js +11 -0
  326. package/dist/data/test-runner/adapter.js.map +1 -1
  327. package/dist/data/test-runner/copy.cjs +114 -0
  328. package/dist/data/test-runner/copy.cjs.map +1 -0
  329. package/dist/data/test-runner/copy.d.ts +47 -0
  330. package/dist/data/test-runner/copy.d.ts.map +1 -0
  331. package/dist/data/test-runner/copy.js +114 -0
  332. package/dist/data/test-runner/copy.js.map +1 -0
  333. package/dist/data/test-runner/index.d.ts +5 -2
  334. package/dist/data/test-runner/index.d.ts.map +1 -1
  335. package/dist/data/test-runner/marks.cjs +143 -0
  336. package/dist/data/test-runner/marks.cjs.map +1 -0
  337. package/dist/data/test-runner/marks.d.ts +30 -0
  338. package/dist/data/test-runner/marks.d.ts.map +1 -0
  339. package/dist/data/test-runner/marks.js +143 -0
  340. package/dist/data/test-runner/marks.js.map +1 -0
  341. package/dist/data/test-runner/status.cjs +27 -44
  342. package/dist/data/test-runner/status.cjs.map +1 -1
  343. package/dist/data/test-runner/status.d.ts +12 -3
  344. package/dist/data/test-runner/status.d.ts.map +1 -1
  345. package/dist/data/test-runner/status.js +27 -44
  346. package/dist/data/test-runner/status.js.map +1 -1
  347. package/dist/data/use-group-windows.cjs +50 -0
  348. package/dist/data/use-group-windows.cjs.map +1 -0
  349. package/dist/data/use-group-windows.d.ts +27 -0
  350. package/dist/data/use-group-windows.d.ts.map +1 -0
  351. package/dist/data/use-group-windows.js +50 -0
  352. package/dist/data/use-group-windows.js.map +1 -0
  353. package/dist/data/verification/adapterViews.cjs +16 -41
  354. package/dist/data/verification/adapterViews.cjs.map +1 -1
  355. package/dist/data/verification/adapterViews.d.ts.map +1 -1
  356. package/dist/data/verification/adapterViews.js +16 -41
  357. package/dist/data/verification/adapterViews.js.map +1 -1
  358. package/dist/data/verification/adapters.cjs +115 -3
  359. package/dist/data/verification/adapters.cjs.map +1 -1
  360. package/dist/data/verification/adapters.d.ts.map +1 -1
  361. package/dist/data/verification/adapters.js +115 -3
  362. package/dist/data/verification/adapters.js.map +1 -1
  363. package/dist/data/verification/verifyReportTests.cjs.map +1 -1
  364. package/dist/data/verification/verifyReportTests.js.map +1 -1
  365. package/dist/data/version-info.cjs +3 -3
  366. package/dist/data/version-info.js +3 -3
  367. package/dist/data.cjs +54 -3
  368. package/dist/data.cjs.map +1 -1
  369. package/dist/data.d.ts +6 -2
  370. package/dist/data.d.ts.map +1 -1
  371. package/dist/data.js +58 -7
  372. package/dist/data.js.map +1 -1
  373. package/dist/hooks/event-hub.cjs +229 -0
  374. package/dist/hooks/event-hub.cjs.map +1 -0
  375. package/dist/hooks/event-hub.d.ts +26 -0
  376. package/dist/hooks/event-hub.d.ts.map +1 -0
  377. package/dist/hooks/event-hub.js +229 -0
  378. package/dist/hooks/event-hub.js.map +1 -0
  379. package/dist/hooks.cjs +2 -0
  380. package/dist/hooks.cjs.map +1 -1
  381. package/dist/hooks.d.ts +1 -0
  382. package/dist/hooks.d.ts.map +1 -1
  383. package/dist/hooks.js +2 -0
  384. package/dist/hooks.js.map +1 -1
  385. package/dist/icons/components/UiLogoEslint.cjs +10 -0
  386. package/dist/icons/components/UiLogoEslint.cjs.map +1 -0
  387. package/dist/icons/components/UiLogoEslint.d.ts +9 -0
  388. package/dist/icons/components/UiLogoEslint.d.ts.map +1 -0
  389. package/dist/icons/components/UiLogoEslint.js +10 -0
  390. package/dist/icons/components/UiLogoEslint.js.map +1 -0
  391. package/dist/icons/components/UiLogoGo.cjs +10 -0
  392. package/dist/icons/components/UiLogoGo.cjs.map +1 -0
  393. package/dist/icons/components/UiLogoGo.d.ts +9 -0
  394. package/dist/icons/components/UiLogoGo.d.ts.map +1 -0
  395. package/dist/icons/components/UiLogoGo.js +10 -0
  396. package/dist/icons/components/UiLogoGo.js.map +1 -0
  397. package/dist/icons/components/UiLogoJest.cjs +10 -0
  398. package/dist/icons/components/UiLogoJest.cjs.map +1 -0
  399. package/dist/icons/components/UiLogoJest.d.ts +9 -0
  400. package/dist/icons/components/UiLogoJest.d.ts.map +1 -0
  401. package/dist/icons/components/UiLogoJest.js +10 -0
  402. package/dist/icons/components/UiLogoJest.js.map +1 -0
  403. package/dist/icons/components/UiLogoMarkdown.cjs +10 -0
  404. package/dist/icons/components/UiLogoMarkdown.cjs.map +1 -0
  405. package/dist/icons/components/UiLogoMarkdown.d.ts +9 -0
  406. package/dist/icons/components/UiLogoMarkdown.d.ts.map +1 -0
  407. package/dist/icons/components/UiLogoMarkdown.js +10 -0
  408. package/dist/icons/components/UiLogoMarkdown.js.map +1 -0
  409. package/dist/icons/components/UiLogoOxc.cjs +10 -0
  410. package/dist/icons/components/UiLogoOxc.cjs.map +1 -0
  411. package/dist/icons/components/UiLogoOxc.d.ts +9 -0
  412. package/dist/icons/components/UiLogoOxc.d.ts.map +1 -0
  413. package/dist/icons/components/UiLogoOxc.js +10 -0
  414. package/dist/icons/components/UiLogoOxc.js.map +1 -0
  415. package/dist/icons/components/UiLogoPlaywright.cjs +10 -0
  416. package/dist/icons/components/UiLogoPlaywright.cjs.map +1 -0
  417. package/dist/icons/components/UiLogoPlaywright.d.ts +9 -0
  418. package/dist/icons/components/UiLogoPlaywright.d.ts.map +1 -0
  419. package/dist/icons/components/UiLogoPlaywright.js +10 -0
  420. package/dist/icons/components/UiLogoPlaywright.js.map +1 -0
  421. package/dist/icons/components/UiLogoPython.cjs +10 -0
  422. package/dist/icons/components/UiLogoPython.cjs.map +1 -0
  423. package/dist/icons/components/UiLogoPython.d.ts +9 -0
  424. package/dist/icons/components/UiLogoPython.d.ts.map +1 -0
  425. package/dist/icons/components/UiLogoPython.js +10 -0
  426. package/dist/icons/components/UiLogoPython.js.map +1 -0
  427. package/dist/icons/components/UiLogoReact.cjs +10 -0
  428. package/dist/icons/components/UiLogoReact.cjs.map +1 -0
  429. package/dist/icons/components/UiLogoReact.d.ts +9 -0
  430. package/dist/icons/components/UiLogoReact.d.ts.map +1 -0
  431. package/dist/icons/components/UiLogoReact.js +10 -0
  432. package/dist/icons/components/UiLogoReact.js.map +1 -0
  433. package/dist/icons/components/UiLogoRuff.cjs +10 -0
  434. package/dist/icons/components/UiLogoRuff.cjs.map +1 -0
  435. package/dist/icons/components/UiLogoRuff.d.ts +9 -0
  436. package/dist/icons/components/UiLogoRuff.d.ts.map +1 -0
  437. package/dist/icons/components/UiLogoRuff.js +10 -0
  438. package/dist/icons/components/UiLogoRuff.js.map +1 -0
  439. package/dist/icons/components/UiLogoTypescript.cjs +10 -0
  440. package/dist/icons/components/UiLogoTypescript.cjs.map +1 -0
  441. package/dist/icons/components/UiLogoTypescript.d.ts +9 -0
  442. package/dist/icons/components/UiLogoTypescript.d.ts.map +1 -0
  443. package/dist/icons/components/UiLogoTypescript.js +10 -0
  444. package/dist/icons/components/UiLogoTypescript.js.map +1 -0
  445. package/dist/icons/components/UiLogoVitest.cjs +10 -0
  446. package/dist/icons/components/UiLogoVitest.cjs.map +1 -0
  447. package/dist/icons/components/UiLogoVitest.d.ts +9 -0
  448. package/dist/icons/components/UiLogoVitest.d.ts.map +1 -0
  449. package/dist/icons/components/UiLogoVitest.js +10 -0
  450. package/dist/icons/components/UiLogoVitest.js.map +1 -0
  451. package/dist/icons/index.d.ts +11 -0
  452. package/dist/icons/index.d.ts.map +1 -1
  453. package/dist/icons/registry.cjs +22 -0
  454. package/dist/icons/registry.cjs.map +1 -1
  455. package/dist/icons/registry.d.ts.map +1 -1
  456. package/dist/icons/registry.js +22 -0
  457. package/dist/icons/registry.js.map +1 -1
  458. package/dist/icons.cjs +22 -0
  459. package/dist/icons.cjs.map +1 -1
  460. package/dist/icons.js +22 -0
  461. package/dist/icons.js.map +1 -1
  462. package/dist/index.cjs +56 -3
  463. package/dist/index.cjs.map +1 -1
  464. package/dist/index.js +60 -7
  465. package/dist/index.js.map +1 -1
  466. package/dist/overlay/DropdownMenuSubmenu.cjs +4 -4
  467. package/dist/overlay/DropdownMenuSubmenu.cjs.map +1 -1
  468. package/dist/overlay/DropdownMenuSubmenu.js +4 -4
  469. package/dist/overlay/DropdownMenuSubmenu.js.map +1 -1
  470. package/dist/overlay/modalStack.cjs +13 -6
  471. package/dist/overlay/modalStack.cjs.map +1 -1
  472. package/dist/overlay/modalStack.d.ts.map +1 -1
  473. package/dist/overlay/modalStack.js +13 -6
  474. package/dist/overlay/modalStack.js.map +1 -1
  475. package/dist/rpc/InlineError.cjs +12 -43
  476. package/dist/rpc/InlineError.cjs.map +1 -1
  477. package/dist/rpc/InlineError.d.ts.map +1 -1
  478. package/dist/rpc/InlineError.js +13 -44
  479. package/dist/rpc/InlineError.js.map +1 -1
  480. package/dist/rpc/OperationScheduleDialog.cjs +63 -10
  481. package/dist/rpc/OperationScheduleDialog.cjs.map +1 -1
  482. package/dist/rpc/OperationScheduleDialog.d.ts +4 -0
  483. package/dist/rpc/OperationScheduleDialog.d.ts.map +1 -1
  484. package/dist/rpc/OperationScheduleDialog.js +63 -10
  485. package/dist/rpc/OperationScheduleDialog.js.map +1 -1
  486. package/dist/rpc/OperationSchedules.cjs +12 -2
  487. package/dist/rpc/OperationSchedules.cjs.map +1 -1
  488. package/dist/rpc/OperationSchedules.d.ts.map +1 -1
  489. package/dist/rpc/OperationSchedules.js +12 -2
  490. package/dist/rpc/OperationSchedules.js.map +1 -1
  491. package/dist/rpc/operation-schedule-model.cjs +2 -0
  492. package/dist/rpc/operation-schedule-model.cjs.map +1 -1
  493. package/dist/rpc/operation-schedule-model.d.ts.map +1 -1
  494. package/dist/rpc/operation-schedule-model.js +2 -0
  495. package/dist/rpc/operation-schedule-model.js.map +1 -1
  496. package/dist/rpc/operation-schedule-types.d.ts +7 -1
  497. package/dist/rpc/operation-schedule-types.d.ts.map +1 -1
  498. package/dist/styles.css +1 -1
  499. package/package.json +1 -1
  500. package/dist/data/test-runner/frameworkIcon.cjs +0 -27
  501. package/dist/data/test-runner/frameworkIcon.cjs.map +0 -1
  502. package/dist/data/test-runner/frameworkIcon.d.ts +0 -3
  503. package/dist/data/test-runner/frameworkIcon.d.ts.map +0 -1
  504. package/dist/data/test-runner/frameworkIcon.js +0 -27
  505. package/dist/data/test-runner/frameworkIcon.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"DropdownMenuSubmenu.js","sources":["../../src/overlay/DropdownMenuSubmenu.tsx"],"sourcesContent":["import { Fragment, useContext, useEffect, useRef, useState } from \"react\";\nimport {\n autoUpdate,\n flip,\n FloatingFocusManager,\n FloatingList,\n FloatingNode,\n FloatingPortal,\n offset,\n safePolygon,\n shift,\n useClick,\n useDismiss,\n useFloating,\n useFloatingNodeId,\n useFloatingParentNodeId,\n useFloatingTree,\n useHover,\n useInteractions,\n useListItem,\n useListNavigation,\n useMergeRefs,\n useRole,\n type UseInteractionsReturn,\n} from \"@floating-ui/react\";\nimport { Icon, type StaticIconComponent } from \"../data/Icon\";\nimport { UiChevronRight } from \"../icons\";\nimport { MENU_POPOVER_CLASS, MenuContext } from \"./dropdownMenuContext\";\nimport { useEscapeLayer, useFloatingZIndex } from \"./modalStack\";\nimport type { DropdownMenuItem } from \"./DropdownMenu\";\nimport { cn } from \"../lib/utils\";\n\n// Shared item surfaces so a leaf renders identically in the root menu or a\n// flyout submenu.\nconst MENU_ITEM_CLASS =\n \"flex w-full items-center gap-2 px-3 py-1.5 text-left text-xs text-popover-foreground hover:bg-accent hover:text-accent-foreground disabled:pointer-events-none disabled:opacity-50\";\nconst MENU_HEADER_CLASS =\n \"select-none px-3 pb-1 pt-2 text-[10px] font-medium uppercase tracking-wide text-muted-foreground\";\n\nfunction MenuItemIcon({\n icon,\n iconColor,\n iconClassName,\n}: {\n icon: string | StaticIconComponent | undefined;\n iconColor: string | undefined;\n iconClassName: string | undefined;\n}) {\n if (!icon) return null;\n return (\n // `text-base` rather than inheriting the row: `Icon` sizes at 1em, so on a\n // `text-xs` row the glyph came out at 12px — smaller than anything a caller\n // puts in the label beside it, and too small to identify at a glance. The\n // row's content box is already 16px tall, so this does not change its height.\n <span\n className={cn(\"inline-flex shrink-0 text-base\", iconClassName)}\n style={iconColor ? { color: iconColor } : undefined}\n >\n <Icon {...(typeof icon === \"string\" ? { name: icon } : { icon })} />\n </span>\n );\n}\n\nfunction MenuLeaf({ item }: { item: DropdownMenuItem }) {\n const menu = useContext(MenuContext);\n const tree = useFloatingTree();\n const listItem = useListItem();\n const isActive = listItem.index === menu.activeIndex;\n\n const activate = () => {\n if (item.disabled) return;\n item.onSelect();\n // A selection closes every open level; each menu subscribes to \"click\".\n tree?.events.emit(\"click\");\n };\n\n return (\n <button\n ref={listItem.ref}\n type=\"button\"\n role=\"menuitem\"\n tabIndex={isActive ? 0 : -1}\n disabled={item.disabled}\n title={item.title}\n className={MENU_ITEM_CLASS}\n {...menu.getItemProps({\n onClick: activate,\n onFocus: () => menu.setHasFocusInside(true),\n onKeyDown: (event) => {\n if (event.key === \"Enter\" || event.key === \" \") {\n event.preventDefault();\n activate();\n }\n },\n })}\n >\n <MenuItemIcon\n icon={item.icon}\n iconColor={item.iconColor}\n iconClassName={item.iconClassName}\n />\n {item.label}\n </button>\n );\n}\n\nfunction MenuSubmenu({ item }: { item: DropdownMenuItem }) {\n const parent = useContext(MenuContext);\n const tree = useFloatingTree();\n const nodeId = useFloatingNodeId();\n const parentId = useFloatingParentNodeId();\n const listItem = useListItem();\n\n const [isOpen, setIsOpen] = useState(false);\n const [activeIndex, setActiveIndex] = useState<number | null>(null);\n const [hasFocusInside, setHasFocusInside] = useState(false);\n const elementsRef = useRef<Array<HTMLElement | null>>([]);\n const floatingZ = useFloatingZIndex();\n\n const { refs, floatingStyles, context } = useFloating<HTMLButtonElement>({\n // nodeId is always defined inside the FloatingTree; guard for the type only.\n ...(nodeId ? { nodeId } : {}),\n open: isOpen,\n onOpenChange: setIsOpen,\n placement: \"right-start\",\n middleware: [\n offset({ mainAxis: 0, alignmentAxis: -4 }),\n flip({ padding: 8 }),\n shift({ padding: 8, crossAxis: true }),\n ],\n whileElementsMounted: autoUpdate,\n });\n\n const hover = useHover(context, {\n delay: { open: 75 },\n handleClose: safePolygon(),\n });\n // Hover opens the flyout for mouse users; click/tap also opens it (touch and\n // keyboard) but never toggles it shut — leaving via safePolygon or selecting a\n // leaf is what closes it.\n const click = useClick(context, { toggle: false });\n const role = useRole(context, { role: \"menu\" });\n // Escape is owned by useEscapeLayer (below) so it dismisses one menu level at\n // a time and cooperates with modals; useDismiss keeps outside-press dismissal.\n const dismiss = useDismiss(context, { escapeKey: false, bubbles: true });\n const listNav = useListNavigation(context, {\n listRef: elementsRef,\n activeIndex,\n nested: true,\n onNavigate: setActiveIndex,\n loop: true,\n });\n const { getReferenceProps, getFloatingProps, getItemProps } = useInteractions(\n [hover, click, role, dismiss, listNav],\n );\n\n useEscapeLayer(isOpen, () => setIsOpen(false));\n\n useEffect(() => {\n if (!tree) return;\n const closeAll = () => setIsOpen(false);\n const closeSiblings = (event: {\n nodeId: string;\n parentId: string | null;\n }) => {\n if (event.nodeId !== nodeId && event.parentId === parentId) {\n setIsOpen(false);\n }\n };\n tree.events.on(\"click\", closeAll);\n tree.events.on(\"menuopen\", closeSiblings);\n return () => {\n tree.events.off(\"click\", closeAll);\n tree.events.off(\"menuopen\", closeSiblings);\n };\n }, [tree, nodeId, parentId]);\n\n useEffect(() => {\n if (isOpen && tree) tree.events.emit(\"menuopen\", { parentId, nodeId });\n }, [isOpen, tree, nodeId, parentId]);\n\n const isActive = listItem.index === parent.activeIndex;\n const referenceRef = useMergeRefs([refs.setReference, listItem.ref]);\n const ariaLabel = typeof item.label === \"string\" ? item.label : undefined;\n\n return (\n <FloatingNode id={nodeId}>\n <button\n ref={referenceRef}\n type=\"button\"\n role=\"menuitem\"\n tabIndex={isActive ? 0 : -1}\n disabled={item.disabled}\n title={item.title}\n aria-haspopup=\"menu\"\n aria-expanded={isOpen}\n data-focus-inside={hasFocusInside ? \"\" : undefined}\n className={MENU_ITEM_CLASS}\n {...parent.getItemProps(\n // Merge the parent's roving-tabindex props with this trigger's own\n // reference props (open on hover/click/ArrowRight). Both prop-getters\n // return an opaque prop bag; the cast bridges the two getter\n // signatures (getReferenceProps -> getItemProps parameter).\n getReferenceProps({\n onFocus: () => {\n setHasFocusInside(false);\n parent.setHasFocusInside(true);\n },\n }) as unknown as Parameters<UseInteractionsReturn[\"getItemProps\"]>[0],\n )}\n >\n <MenuItemIcon\n icon={item.icon}\n iconColor={item.iconColor}\n iconClassName={item.iconClassName}\n />\n <span className=\"min-w-0 flex-1 truncate\">{item.label}</span>\n <Icon icon={UiChevronRight} className=\"ml-auto shrink-0 opacity-60\" />\n </button>\n <MenuContext.Provider\n value={{\n getItemProps,\n activeIndex,\n setActiveIndex,\n setHasFocusInside,\n isOpen,\n }}\n >\n <FloatingList elementsRef={elementsRef}>\n {isOpen && (\n <FloatingPortal>\n <FloatingFocusManager\n context={context}\n modal={false}\n initialFocus={-1}\n returnFocus={false}\n >\n <div\n ref={refs.setFloating}\n role=\"menu\"\n style={{ ...floatingStyles, zIndex: floatingZ }}\n className={MENU_POPOVER_CLASS}\n {...getFloatingProps()}\n aria-label={ariaLabel}\n {...(ariaLabel ? { \"aria-labelledby\": undefined } : {})}\n >\n {item.header != null && (\n <div className=\"border-b border-border px-3 py-1.5\">\n {item.header}\n </div>\n )}\n <MenuItemList items={item.children ?? []} />\n </div>\n </FloatingFocusManager>\n </FloatingPortal>\n )}\n </FloatingList>\n </MenuContext.Provider>\n </FloatingNode>\n );\n}\n\n/**\n * Renders one menu level: a leaf `menuitem` button, or a submenu trigger when\n * the item has `children`. A group header renders above the first item of each\n * contiguous group (headers are not focusable, so keyboard navigation stays\n * dense over the interactive items). Must be rendered inside a `FloatingList`\n * whose `elementsRef` backs the enclosing menu's list navigation.\n */\nexport function MenuItemList({ items }: { items: DropdownMenuItem[] }) {\n return (\n <>\n {items.map((item, index) => {\n const showHeader =\n item.group != null && item.group !== items[index - 1]?.group;\n const hasChildren = !!item.children && item.children.length > 0;\n return (\n <Fragment key={index}>\n {showHeader && (\n <div role=\"presentation\" className={MENU_HEADER_CLASS}>\n {item.group}\n </div>\n )}\n {hasChildren ? (\n <MenuSubmenu item={item} />\n ) : (\n <MenuLeaf item={item} />\n )}\n </Fragment>\n );\n })}\n </>\n );\n}\n"],"names":["Fragment"],"mappings":"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"}
1
+ {"version":3,"file":"DropdownMenuSubmenu.js","sources":["../../src/overlay/DropdownMenuSubmenu.tsx"],"sourcesContent":["import { Fragment, useContext, useEffect, useRef, useState } from \"react\";\nimport {\n autoUpdate,\n flip,\n FloatingFocusManager,\n FloatingList,\n FloatingNode,\n FloatingPortal,\n offset,\n safePolygon,\n shift,\n useClick,\n useDismiss,\n useFloating,\n useFloatingNodeId,\n useFloatingParentNodeId,\n useFloatingTree,\n useHover,\n useInteractions,\n useListItem,\n useListNavigation,\n useMergeRefs,\n useRole,\n type UseInteractionsReturn,\n} from \"@floating-ui/react\";\nimport { Icon, type StaticIconComponent } from \"../data/Icon\";\nimport { UiChevronRight } from \"../icons\";\nimport { MENU_POPOVER_CLASS, MenuContext } from \"./dropdownMenuContext\";\nimport { useEscapeLayer, useFloatingZIndex } from \"./modalStack\";\nimport type { DropdownMenuItem } from \"./DropdownMenu\";\nimport { cn } from \"../lib/utils\";\n\n// Shared item surfaces so a leaf renders identically in the root menu or a\n// flyout submenu.\nconst MENU_ITEM_CLASS =\n \"flex w-full items-center gap-2 px-3 py-1.5 text-left text-xs text-popover-foreground hover:bg-accent hover:text-accent-foreground disabled:pointer-events-none disabled:opacity-50\";\nconst MENU_HEADER_CLASS =\n \"select-none px-3 pb-1 pt-2 text-[10px] font-medium uppercase tracking-wide text-muted-foreground\";\n\nfunction MenuItemIcon({\n icon,\n iconColor,\n iconClassName,\n}: {\n icon: string | StaticIconComponent | undefined;\n iconColor: string | undefined;\n iconClassName: string | undefined;\n}) {\n if (!icon) return null;\n return (\n // `text-base` rather than inheriting the row: `Icon` sizes at 1em, so on a\n // `text-xs` row the glyph came out at 12px — smaller than anything a caller\n // puts in the label beside it, and too small to identify at a glance. The\n // row's content box is already 16px tall, so this does not change its height.\n <span\n className={cn(\"inline-flex shrink-0 text-base\", iconClassName)}\n style={iconColor ? { color: iconColor } : undefined}\n >\n <Icon {...(typeof icon === \"string\" ? { name: icon } : { icon })} />\n </span>\n );\n}\n\nfunction MenuLeaf({ item }: { item: DropdownMenuItem }) {\n const menu = useContext(MenuContext);\n const tree = useFloatingTree();\n const listItem = useListItem();\n const isActive = listItem.index === menu.activeIndex;\n\n const activate = () => {\n if (item.disabled) return;\n item.onSelect();\n // A selection closes every open level; each menu subscribes to \"click\".\n tree?.events.emit(\"click\");\n };\n\n return (\n <button\n ref={listItem.ref}\n type=\"button\"\n role=\"menuitem\"\n tabIndex={isActive ? 0 : -1}\n disabled={item.disabled}\n title={item.title}\n className={MENU_ITEM_CLASS}\n {...menu.getItemProps({\n onClick: activate,\n onFocus: () => menu.setHasFocusInside(true),\n onKeyDown: (event) => {\n if (event.key === \"Enter\" || event.key === \" \") {\n event.preventDefault();\n activate();\n }\n },\n })}\n >\n <MenuItemIcon\n icon={item.icon}\n iconColor={item.iconColor}\n iconClassName={item.iconClassName}\n />\n {item.label}\n </button>\n );\n}\n\nfunction MenuSubmenu({ item }: { item: DropdownMenuItem }) {\n const parent = useContext(MenuContext);\n const tree = useFloatingTree();\n const nodeId = useFloatingNodeId();\n const parentId = useFloatingParentNodeId();\n const listItem = useListItem();\n\n const [isOpen, setIsOpen] = useState(false);\n const [activeIndex, setActiveIndex] = useState<number | null>(null);\n const [hasFocusInside, setHasFocusInside] = useState(false);\n const elementsRef = useRef<Array<HTMLElement | null>>([]);\n const floatingZ = useFloatingZIndex();\n\n const { refs, floatingStyles, context } = useFloating<HTMLButtonElement>({\n // nodeId is always defined inside the FloatingTree; guard for the type only.\n ...(nodeId ? { nodeId } : {}),\n open: isOpen,\n onOpenChange: setIsOpen,\n placement: \"right-start\",\n middleware: [\n offset({ mainAxis: 0, alignmentAxis: -4 }),\n flip({ padding: 8 }),\n shift({ padding: 8, crossAxis: true }),\n ],\n whileElementsMounted: autoUpdate,\n });\n\n const hover = useHover(context, {\n delay: { open: 75 },\n handleClose: safePolygon(),\n });\n // Hover opens the flyout for mouse users; click/tap also opens it (touch and\n // keyboard) but never toggles it shut — leaving via safePolygon or selecting a\n // leaf is what closes it.\n const click = useClick(context, { toggle: false });\n const role = useRole(context, { role: \"menu\" });\n // Escape is owned by useEscapeLayer (below) so it dismisses one menu level at\n // a time and cooperates with modals; useDismiss keeps outside-press dismissal.\n const dismiss = useDismiss(context, { escapeKey: false, bubbles: true });\n const listNav = useListNavigation(context, {\n listRef: elementsRef,\n activeIndex,\n nested: true,\n onNavigate: setActiveIndex,\n loop: true,\n });\n const { getReferenceProps, getFloatingProps, getItemProps } = useInteractions(\n [hover, click, role, dismiss, listNav],\n );\n\n useEscapeLayer(isOpen, () => context.onOpenChange(false));\n\n useEffect(() => {\n if (!tree) return;\n const closeAll = () => context.onOpenChange(false);\n const closeSiblings = (event: {\n nodeId: string;\n parentId: string | null;\n }) => {\n if (event.nodeId !== nodeId && event.parentId === parentId) {\n context.onOpenChange(false);\n }\n };\n tree.events.on(\"click\", closeAll);\n tree.events.on(\"menuopen\", closeSiblings);\n return () => {\n tree.events.off(\"click\", closeAll);\n tree.events.off(\"menuopen\", closeSiblings);\n };\n }, [tree, nodeId, parentId, context.onOpenChange]);\n\n useEffect(() => {\n if (isOpen && tree) tree.events.emit(\"menuopen\", { parentId, nodeId });\n }, [isOpen, tree, nodeId, parentId]);\n\n const isActive = listItem.index === parent.activeIndex;\n const referenceRef = useMergeRefs([refs.setReference, listItem.ref]);\n const ariaLabel = typeof item.label === \"string\" ? item.label : undefined;\n\n return (\n <FloatingNode id={nodeId}>\n <button\n ref={referenceRef}\n type=\"button\"\n role=\"menuitem\"\n tabIndex={isActive ? 0 : -1}\n disabled={item.disabled}\n title={item.title}\n aria-haspopup=\"menu\"\n aria-expanded={isOpen}\n data-focus-inside={hasFocusInside ? \"\" : undefined}\n className={MENU_ITEM_CLASS}\n {...parent.getItemProps(\n // Merge the parent's roving-tabindex props with this trigger's own\n // reference props (open on hover/click/ArrowRight). Both prop-getters\n // return an opaque prop bag; the cast bridges the two getter\n // signatures (getReferenceProps -> getItemProps parameter).\n getReferenceProps({\n onFocus: () => {\n setHasFocusInside(false);\n parent.setHasFocusInside(true);\n },\n }) as unknown as Parameters<UseInteractionsReturn[\"getItemProps\"]>[0],\n )}\n >\n <MenuItemIcon\n icon={item.icon}\n iconColor={item.iconColor}\n iconClassName={item.iconClassName}\n />\n <span className=\"min-w-0 flex-1 truncate\">{item.label}</span>\n <Icon icon={UiChevronRight} className=\"ml-auto shrink-0 opacity-60\" />\n </button>\n <MenuContext.Provider\n value={{\n getItemProps,\n activeIndex,\n setActiveIndex,\n setHasFocusInside,\n isOpen,\n }}\n >\n <FloatingList elementsRef={elementsRef}>\n {isOpen && (\n <FloatingPortal>\n <FloatingFocusManager\n context={context}\n modal={false}\n initialFocus={-1}\n returnFocus={false}\n >\n <div\n ref={refs.setFloating}\n role=\"menu\"\n style={{ ...floatingStyles, zIndex: floatingZ }}\n className={MENU_POPOVER_CLASS}\n {...getFloatingProps()}\n aria-label={ariaLabel}\n {...(ariaLabel ? { \"aria-labelledby\": undefined } : {})}\n >\n {item.header != null && (\n <div className=\"border-b border-border px-3 py-1.5\">\n {item.header}\n </div>\n )}\n <MenuItemList items={item.children ?? []} />\n </div>\n </FloatingFocusManager>\n </FloatingPortal>\n )}\n </FloatingList>\n </MenuContext.Provider>\n </FloatingNode>\n );\n}\n\n/**\n * Renders one menu level: a leaf `menuitem` button, or a submenu trigger when\n * the item has `children`. A group header renders above the first item of each\n * contiguous group (headers are not focusable, so keyboard navigation stays\n * dense over the interactive items). Must be rendered inside a `FloatingList`\n * whose `elementsRef` backs the enclosing menu's list navigation.\n */\nexport function MenuItemList({ items }: { items: DropdownMenuItem[] }) {\n return (\n <>\n {items.map((item, index) => {\n const showHeader =\n item.group != null && item.group !== items[index - 1]?.group;\n const hasChildren = !!item.children && item.children.length > 0;\n return (\n <Fragment key={index}>\n {showHeader && (\n <div role=\"presentation\" className={MENU_HEADER_CLASS}>\n {item.group}\n </div>\n )}\n {hasChildren ? (\n <MenuSubmenu item={item} />\n ) : (\n <MenuLeaf item={item} />\n )}\n </Fragment>\n );\n })}\n </>\n );\n}\n"],"names":["Fragment"],"mappings":"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"}
@@ -23,11 +23,12 @@ function onEscapeKeyDown(event) {
23
23
  if (event.defaultPrevented || event.key !== "Escape" || event.isComposing || event.keyCode === 229) {
24
24
  return;
25
25
  }
26
- const top = escapeStack[escapeStack.length - 1];
26
+ const top = escapeStack.findLast((entry) => !entry.dismissed);
27
27
  if (!top) return;
28
28
  event.preventDefault();
29
29
  event.stopPropagation();
30
30
  event.stopImmediatePropagation();
31
+ top.dismissed = true;
31
32
  top.onEscape();
32
33
  }
33
34
  function ensureEscapeListener() {
@@ -66,14 +67,20 @@ function useEscapeLayer(open, onEscape, enabled = true) {
66
67
  const id = react.useId();
67
68
  const onEscapeRef = react.useRef(onEscape);
68
69
  onEscapeRef.current = onEscape;
70
+ const entryRef = react.useRef(null);
71
+ react.useEffect(() => {
72
+ if (entryRef.current) entryRef.current.dismissed = false;
73
+ });
69
74
  react.useEffect(() => {
70
75
  if (!open || !enabled) return;
71
76
  ensureEscapeListener();
72
- escapeStack.push({
73
- id,
74
- onEscape: () => onEscapeRef.current()
75
- });
76
- return () => removeEscapeLayer(id);
77
+ const entry = { id, dismissed: false, onEscape: () => onEscapeRef.current() };
78
+ entryRef.current = entry;
79
+ escapeStack.push(entry);
80
+ return () => {
81
+ entryRef.current = null;
82
+ removeEscapeLayer(id);
83
+ };
77
84
  }, [enabled, id, open]);
78
85
  }
79
86
  function useTourLayer(active) {
@@ -1 +1 @@
1
- {"version":3,"file":"modalStack.cjs","sources":["../../src/overlay/modalStack.ts"],"sourcesContent":["import { useEffect, useId, useRef, useSyncExternalStore } from \"react\";\nimport { zIndex } from \"./zIndex\";\n\n// A process-wide stack of the currently open modals, topmost last. Modals mount\n// independently (no shared provider), so the stack lives at module scope and is\n// shared through useSyncExternalStore. It lets nested modals cooperate: only the\n// topmost reacts to Escape, and each renders above the one it opened over.\nconst stack: string[] = [];\nconst listeners = new Set<() => void>();\nconst escapeStack: Array<{ id: string; onEscape: () => void }> = [];\nlet escapeDocument: Document | null = null;\n// Running guided tours. A tour dims the page from `zIndex.tour`, far above the\n// modal band, so floating content opened *during* a tour (the menu a step tells\n// the user to open) has to clear that dim or it renders invisibly underneath.\nlet tourLayers = 0;\n\nfunction emit() {\n for (const listener of listeners) listener();\n}\n\nfunction subscribe(listener: () => void) {\n listeners.add(listener);\n return () => {\n listeners.delete(listener);\n };\n}\n\n// The snapshot is the stack identity plus the tour-layer count; it only changes\n// when an entry is pushed or popped, so subscribers re-render exactly when their\n// position could have moved.\nfunction getSnapshot() {\n return `${tourLayers}:` + stack.join(\"\\u0000\");\n}\n\nfunction onEscapeKeyDown(event: KeyboardEvent) {\n if (\n event.defaultPrevented ||\n event.key !== \"Escape\" ||\n event.isComposing ||\n (event as KeyboardEvent & { keyCode?: number }).keyCode === 229\n ) {\n return;\n }\n\n const top = escapeStack[escapeStack.length - 1];\n if (!top) return;\n\n event.preventDefault();\n event.stopPropagation();\n event.stopImmediatePropagation();\n top.onEscape();\n}\n\nfunction ensureEscapeListener() {\n if (escapeDocument || typeof document === \"undefined\") return;\n escapeDocument = document;\n escapeDocument.addEventListener(\"keydown\", onEscapeKeyDown);\n}\n\nfunction removeEscapeLayer(id: string) {\n const index = escapeStack.findIndex((entry) => entry.id === id);\n if (index !== -1) escapeStack.splice(index, 1);\n\n if (escapeStack.length === 0 && escapeDocument) {\n escapeDocument.removeEventListener(\"keydown\", onEscapeKeyDown);\n escapeDocument = null;\n }\n}\n\nexport type ModalStackPosition = {\n /** Whether this modal is the topmost open one and should own global affordances. */\n isTop: boolean;\n /** Zero-based depth in the stack; drives the stacking order of nested modals. */\n depth: number;\n};\n\n/**\n * Registers a modal in the global stack while `open`, returning its live\n * position. Used so a nested modal sits above its opener and only the topmost\n * modal closes on Escape.\n */\nexport function useModalStack(open: boolean): ModalStackPosition {\n const id = useId();\n useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n\n useEffect(() => {\n if (!open) return;\n stack.push(id);\n emit();\n return () => {\n const index = stack.indexOf(id);\n if (index !== -1) stack.splice(index, 1);\n emit();\n };\n }, [open, id]);\n\n const depth = stack.indexOf(id);\n return {\n isTop: depth !== -1 && depth === stack.length - 1,\n depth: depth === -1 ? 0 : depth,\n };\n}\n\n/**\n * Registers an Escape-closeable overlay while `open`. The topmost registered\n * layer owns Escape, so a keypress dismisses one dialog/menu layer at a time.\n */\nexport function useEscapeLayer(open: boolean, onEscape: () => void, enabled = true) {\n const id = useId();\n const onEscapeRef = useRef(onEscape);\n onEscapeRef.current = onEscape;\n\n useEffect(() => {\n if (!open || !enabled) return;\n\n ensureEscapeListener();\n escapeStack.push({\n id,\n onEscape: () => onEscapeRef.current(),\n });\n\n return () => removeEscapeLayer(id);\n }, [enabled, id, open]);\n}\n\n/**\n * Registers a running guided tour while `active`, so floating layers lift above\n * its dim. Symmetric with `useModalStack`, but a count rather than a stack: the\n * tour overlay does not nest.\n */\nexport function useTourLayer(active: boolean): void {\n useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n\n useEffect(() => {\n if (!active) return;\n tourLayers += 1;\n emit();\n return () => {\n tourLayers -= 1;\n emit();\n };\n }, [active]);\n}\n\n/**\n * z-index a floating layer (dropdown / combobox / tooltip / popover) should use\n * so it renders above any open modal — and below the next nested modal — or at\n * the popover floor when no modal is open. While a guided tour runs, the value\n * also clears the tour's dim and step card, so a step that says \"open this menu\"\n * shows the menu rather than hiding it under the overlay. Subscribes to the\n * modal stack so the value tracks modals and tours opening and closing.\n */\nexport function useFloatingZIndex(): number {\n useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n const base =\n stack.length === 0\n ? zIndex.popover\n : zIndex.modal + (stack.length - 1) * zIndex.modalStep + zIndex.popoverOverModalOffset;\n if (tourLayers === 0) return base;\n return Math.max(base, zIndex.tour + zIndex.tourCardOffset + zIndex.popoverOverModalOffset);\n}\n"],"names":["useId","useSyncExternalStore","useEffect","useRef","zIndex"],"mappings":"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"}
1
+ {"version":3,"file":"modalStack.cjs","sources":["../../src/overlay/modalStack.ts"],"sourcesContent":["import { useEffect, useId, useRef, useSyncExternalStore } from \"react\";\nimport { zIndex } from \"./zIndex\";\n\n// A process-wide stack of the currently open modals, topmost last. Modals mount\n// independently (no shared provider), so the stack lives at module scope and is\n// shared through useSyncExternalStore. It lets nested modals cooperate: only the\n// topmost reacts to Escape, and each renders above the one it opened over.\nconst stack: string[] = [];\nconst listeners = new Set<() => void>();\n// `dismissed` marks a layer whose onEscape already ran but whose close has not\n// committed yet, so a quick second Escape reaches the layer beneath it.\ntype EscapeLayer = { id: string; dismissed: boolean; onEscape: () => void };\nconst escapeStack: EscapeLayer[] = [];\nlet escapeDocument: Document | null = null;\n// Running guided tours. A tour dims the page from `zIndex.tour`, far above the\n// modal band, so floating content opened *during* a tour (the menu a step tells\n// the user to open) has to clear that dim or it renders invisibly underneath.\nlet tourLayers = 0;\n\nfunction emit() {\n for (const listener of listeners) listener();\n}\n\nfunction subscribe(listener: () => void) {\n listeners.add(listener);\n return () => {\n listeners.delete(listener);\n };\n}\n\n// The snapshot is the stack identity plus the tour-layer count; it only changes\n// when an entry is pushed or popped, so subscribers re-render exactly when their\n// position could have moved.\nfunction getSnapshot() {\n return `${tourLayers}:` + stack.join(\"\\u0000\");\n}\n\nfunction onEscapeKeyDown(event: KeyboardEvent) {\n if (\n event.defaultPrevented ||\n event.key !== \"Escape\" ||\n event.isComposing ||\n (event as KeyboardEvent & { keyCode?: number }).keyCode === 229\n ) {\n return;\n }\n\n const top = escapeStack.findLast((entry) => !entry.dismissed);\n if (!top) return;\n\n event.preventDefault();\n event.stopPropagation();\n event.stopImmediatePropagation();\n top.dismissed = true;\n top.onEscape();\n}\n\nfunction ensureEscapeListener() {\n if (escapeDocument || typeof document === \"undefined\") return;\n escapeDocument = document;\n escapeDocument.addEventListener(\"keydown\", onEscapeKeyDown);\n}\n\nfunction removeEscapeLayer(id: string) {\n const index = escapeStack.findIndex((entry) => entry.id === id);\n if (index !== -1) escapeStack.splice(index, 1);\n\n if (escapeStack.length === 0 && escapeDocument) {\n escapeDocument.removeEventListener(\"keydown\", onEscapeKeyDown);\n escapeDocument = null;\n }\n}\n\nexport type ModalStackPosition = {\n /** Whether this modal is the topmost open one and should own global affordances. */\n isTop: boolean;\n /** Zero-based depth in the stack; drives the stacking order of nested modals. */\n depth: number;\n};\n\n/**\n * Registers a modal in the global stack while `open`, returning its live\n * position. Used so a nested modal sits above its opener and only the topmost\n * modal closes on Escape.\n */\nexport function useModalStack(open: boolean): ModalStackPosition {\n const id = useId();\n useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n\n useEffect(() => {\n if (!open) return;\n stack.push(id);\n emit();\n return () => {\n const index = stack.indexOf(id);\n if (index !== -1) stack.splice(index, 1);\n emit();\n };\n }, [open, id]);\n\n const depth = stack.indexOf(id);\n return {\n isTop: depth !== -1 && depth === stack.length - 1,\n depth: depth === -1 ? 0 : depth,\n };\n}\n\n/**\n * Registers an Escape-closeable overlay while `open`. The topmost registered\n * layer owns Escape, so a keypress dismisses one dialog/menu layer at a time.\n */\nexport function useEscapeLayer(open: boolean, onEscape: () => void, enabled = true) {\n const id = useId();\n const onEscapeRef = useRef(onEscape);\n onEscapeRef.current = onEscape;\n const entryRef = useRef<EscapeLayer | null>(null);\n\n // A dismissed layer that re-rendered without closing owns Escape again.\n useEffect(() => {\n if (entryRef.current) entryRef.current.dismissed = false;\n });\n\n useEffect(() => {\n if (!open || !enabled) return;\n\n ensureEscapeListener();\n const entry: EscapeLayer = { id, dismissed: false, onEscape: () => onEscapeRef.current() };\n entryRef.current = entry;\n escapeStack.push(entry);\n\n return () => {\n entryRef.current = null;\n removeEscapeLayer(id);\n };\n }, [enabled, id, open]);\n}\n\n/**\n * Registers a running guided tour while `active`, so floating layers lift above\n * its dim. Symmetric with `useModalStack`, but a count rather than a stack: the\n * tour overlay does not nest.\n */\nexport function useTourLayer(active: boolean): void {\n useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n\n useEffect(() => {\n if (!active) return;\n tourLayers += 1;\n emit();\n return () => {\n tourLayers -= 1;\n emit();\n };\n }, [active]);\n}\n\n/**\n * z-index a floating layer (dropdown / combobox / tooltip / popover) should use\n * so it renders above any open modal — and below the next nested modal — or at\n * the popover floor when no modal is open. While a guided tour runs, the value\n * also clears the tour's dim and step card, so a step that says \"open this menu\"\n * shows the menu rather than hiding it under the overlay. Subscribes to the\n * modal stack so the value tracks modals and tours opening and closing.\n */\nexport function useFloatingZIndex(): number {\n useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n const base =\n stack.length === 0\n ? zIndex.popover\n : zIndex.modal + (stack.length - 1) * zIndex.modalStep + zIndex.popoverOverModalOffset;\n if (tourLayers === 0) return base;\n return Math.max(base, zIndex.tour + zIndex.tourCardOffset + zIndex.popoverOverModalOffset);\n}\n"],"names":["useId","useSyncExternalStore","useEffect","useRef","zIndex"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"modalStack.d.ts","sourceRoot":"","sources":["../../src/overlay/modalStack.ts"],"names":[],"mappings":"AAqEA,MAAM,MAAM,kBAAkB,GAAG;IAC/B,oFAAoF;IACpF,KAAK,EAAE,OAAO,CAAC;IACf,iFAAiF;IACjF,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,OAAO,GAAG,kBAAkB,CAoB/D;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,IAAI,EAAE,OAAO,UAAO,QAgBjF;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI,CAYlD;AAED;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,IAAI,MAAM,CAQ1C"}
1
+ {"version":3,"file":"modalStack.d.ts","sourceRoot":"","sources":["../../src/overlay/modalStack.ts"],"names":[],"mappings":"AAyEA,MAAM,MAAM,kBAAkB,GAAG;IAC/B,oFAAoF;IACpF,KAAK,EAAE,OAAO,CAAC;IACf,iFAAiF;IACjF,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,OAAO,GAAG,kBAAkB,CAoB/D;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,IAAI,EAAE,OAAO,UAAO,QAwBjF;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI,CAYlD;AAED;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,IAAI,MAAM,CAQ1C"}
@@ -21,11 +21,12 @@ function onEscapeKeyDown(event) {
21
21
  if (event.defaultPrevented || event.key !== "Escape" || event.isComposing || event.keyCode === 229) {
22
22
  return;
23
23
  }
24
- const top = escapeStack[escapeStack.length - 1];
24
+ const top = escapeStack.findLast((entry) => !entry.dismissed);
25
25
  if (!top) return;
26
26
  event.preventDefault();
27
27
  event.stopPropagation();
28
28
  event.stopImmediatePropagation();
29
+ top.dismissed = true;
29
30
  top.onEscape();
30
31
  }
31
32
  function ensureEscapeListener() {
@@ -64,14 +65,20 @@ function useEscapeLayer(open, onEscape, enabled = true) {
64
65
  const id = useId();
65
66
  const onEscapeRef = useRef(onEscape);
66
67
  onEscapeRef.current = onEscape;
68
+ const entryRef = useRef(null);
69
+ useEffect(() => {
70
+ if (entryRef.current) entryRef.current.dismissed = false;
71
+ });
67
72
  useEffect(() => {
68
73
  if (!open || !enabled) return;
69
74
  ensureEscapeListener();
70
- escapeStack.push({
71
- id,
72
- onEscape: () => onEscapeRef.current()
73
- });
74
- return () => removeEscapeLayer(id);
75
+ const entry = { id, dismissed: false, onEscape: () => onEscapeRef.current() };
76
+ entryRef.current = entry;
77
+ escapeStack.push(entry);
78
+ return () => {
79
+ entryRef.current = null;
80
+ removeEscapeLayer(id);
81
+ };
75
82
  }, [enabled, id, open]);
76
83
  }
77
84
  function useTourLayer(active) {
@@ -1 +1 @@
1
- {"version":3,"file":"modalStack.js","sources":["../../src/overlay/modalStack.ts"],"sourcesContent":["import { useEffect, useId, useRef, useSyncExternalStore } from \"react\";\nimport { zIndex } from \"./zIndex\";\n\n// A process-wide stack of the currently open modals, topmost last. Modals mount\n// independently (no shared provider), so the stack lives at module scope and is\n// shared through useSyncExternalStore. It lets nested modals cooperate: only the\n// topmost reacts to Escape, and each renders above the one it opened over.\nconst stack: string[] = [];\nconst listeners = new Set<() => void>();\nconst escapeStack: Array<{ id: string; onEscape: () => void }> = [];\nlet escapeDocument: Document | null = null;\n// Running guided tours. A tour dims the page from `zIndex.tour`, far above the\n// modal band, so floating content opened *during* a tour (the menu a step tells\n// the user to open) has to clear that dim or it renders invisibly underneath.\nlet tourLayers = 0;\n\nfunction emit() {\n for (const listener of listeners) listener();\n}\n\nfunction subscribe(listener: () => void) {\n listeners.add(listener);\n return () => {\n listeners.delete(listener);\n };\n}\n\n// The snapshot is the stack identity plus the tour-layer count; it only changes\n// when an entry is pushed or popped, so subscribers re-render exactly when their\n// position could have moved.\nfunction getSnapshot() {\n return `${tourLayers}:` + stack.join(\"\\u0000\");\n}\n\nfunction onEscapeKeyDown(event: KeyboardEvent) {\n if (\n event.defaultPrevented ||\n event.key !== \"Escape\" ||\n event.isComposing ||\n (event as KeyboardEvent & { keyCode?: number }).keyCode === 229\n ) {\n return;\n }\n\n const top = escapeStack[escapeStack.length - 1];\n if (!top) return;\n\n event.preventDefault();\n event.stopPropagation();\n event.stopImmediatePropagation();\n top.onEscape();\n}\n\nfunction ensureEscapeListener() {\n if (escapeDocument || typeof document === \"undefined\") return;\n escapeDocument = document;\n escapeDocument.addEventListener(\"keydown\", onEscapeKeyDown);\n}\n\nfunction removeEscapeLayer(id: string) {\n const index = escapeStack.findIndex((entry) => entry.id === id);\n if (index !== -1) escapeStack.splice(index, 1);\n\n if (escapeStack.length === 0 && escapeDocument) {\n escapeDocument.removeEventListener(\"keydown\", onEscapeKeyDown);\n escapeDocument = null;\n }\n}\n\nexport type ModalStackPosition = {\n /** Whether this modal is the topmost open one and should own global affordances. */\n isTop: boolean;\n /** Zero-based depth in the stack; drives the stacking order of nested modals. */\n depth: number;\n};\n\n/**\n * Registers a modal in the global stack while `open`, returning its live\n * position. Used so a nested modal sits above its opener and only the topmost\n * modal closes on Escape.\n */\nexport function useModalStack(open: boolean): ModalStackPosition {\n const id = useId();\n useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n\n useEffect(() => {\n if (!open) return;\n stack.push(id);\n emit();\n return () => {\n const index = stack.indexOf(id);\n if (index !== -1) stack.splice(index, 1);\n emit();\n };\n }, [open, id]);\n\n const depth = stack.indexOf(id);\n return {\n isTop: depth !== -1 && depth === stack.length - 1,\n depth: depth === -1 ? 0 : depth,\n };\n}\n\n/**\n * Registers an Escape-closeable overlay while `open`. The topmost registered\n * layer owns Escape, so a keypress dismisses one dialog/menu layer at a time.\n */\nexport function useEscapeLayer(open: boolean, onEscape: () => void, enabled = true) {\n const id = useId();\n const onEscapeRef = useRef(onEscape);\n onEscapeRef.current = onEscape;\n\n useEffect(() => {\n if (!open || !enabled) return;\n\n ensureEscapeListener();\n escapeStack.push({\n id,\n onEscape: () => onEscapeRef.current(),\n });\n\n return () => removeEscapeLayer(id);\n }, [enabled, id, open]);\n}\n\n/**\n * Registers a running guided tour while `active`, so floating layers lift above\n * its dim. Symmetric with `useModalStack`, but a count rather than a stack: the\n * tour overlay does not nest.\n */\nexport function useTourLayer(active: boolean): void {\n useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n\n useEffect(() => {\n if (!active) return;\n tourLayers += 1;\n emit();\n return () => {\n tourLayers -= 1;\n emit();\n };\n }, [active]);\n}\n\n/**\n * z-index a floating layer (dropdown / combobox / tooltip / popover) should use\n * so it renders above any open modal — and below the next nested modal — or at\n * the popover floor when no modal is open. While a guided tour runs, the value\n * also clears the tour's dim and step card, so a step that says \"open this menu\"\n * shows the menu rather than hiding it under the overlay. Subscribes to the\n * modal stack so the value tracks modals and tours opening and closing.\n */\nexport function useFloatingZIndex(): number {\n useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n const base =\n stack.length === 0\n ? zIndex.popover\n : zIndex.modal + (stack.length - 1) * zIndex.modalStep + zIndex.popoverOverModalOffset;\n if (tourLayers === 0) return base;\n return Math.max(base, zIndex.tour + zIndex.tourCardOffset + zIndex.popoverOverModalOffset);\n}\n"],"names":[],"mappings":";;AAOA,MAAM,QAAkB,CAAA;AACxB,MAAM,gCAAgB,IAAA;AACtB,MAAM,cAA2D,CAAA;AACjE,IAAI,iBAAkC;AAItC,IAAI,aAAa;AAEjB,SAAS,OAAO;AACd,aAAW,YAAY,UAAW,UAAA;AACpC;AAEA,SAAS,UAAU,UAAsB;AACvC,YAAU,IAAI,QAAQ;AACtB,SAAO,MAAM;AACX,cAAU,OAAO,QAAQ;AAAA,EAC3B;AACF;AAKA,SAAS,cAAc;AACrB,SAAO,GAAG,UAAU,MAAM,MAAM,KAAK,IAAQ;AAC/C;AAEA,SAAS,gBAAgB,OAAsB;AAC7C,MACE,MAAM,oBACN,MAAM,QAAQ,YACd,MAAM,eACL,MAA+C,YAAY,KAC5D;AACA;AAAA,EACF;AAEA,QAAM,MAAM,YAAY,YAAY,SAAS,CAAC;AAC9C,MAAI,CAAC,IAAK;AAEV,QAAM,eAAA;AACN,QAAM,gBAAA;AACN,QAAM,yBAAA;AACN,MAAI,SAAA;AACN;AAEA,SAAS,uBAAuB;AAC9B,MAAI,kBAAkB,OAAO,aAAa,YAAa;AACvD,mBAAiB;AACjB,iBAAe,iBAAiB,WAAW,eAAe;AAC5D;AAEA,SAAS,kBAAkB,IAAY;AACrC,QAAM,QAAQ,YAAY,UAAU,CAAC,UAAU,MAAM,OAAO,EAAE;AAC9D,MAAI,UAAU,GAAI,aAAY,OAAO,OAAO,CAAC;AAE7C,MAAI,YAAY,WAAW,KAAK,gBAAgB;AAC9C,mBAAe,oBAAoB,WAAW,eAAe;AAC7D,qBAAiB;AAAA,EACnB;AACF;AAcO,SAAS,cAAc,MAAmC;AAC/D,QAAM,KAAK,MAAA;AACX,uBAAqB,WAAW,aAAa,WAAW;AAExD,YAAU,MAAM;AACd,QAAI,CAAC,KAAM;AACX,UAAM,KAAK,EAAE;AACb,SAAA;AACA,WAAO,MAAM;AACX,YAAM,QAAQ,MAAM,QAAQ,EAAE;AAC9B,UAAI,UAAU,GAAI,OAAM,OAAO,OAAO,CAAC;AACvC,WAAA;AAAA,IACF;AAAA,EACF,GAAG,CAAC,MAAM,EAAE,CAAC;AAEb,QAAM,QAAQ,MAAM,QAAQ,EAAE;AAC9B,SAAO;AAAA,IACL,OAAO,UAAU,MAAM,UAAU,MAAM,SAAS;AAAA,IAChD,OAAO,UAAU,KAAK,IAAI;AAAA,EAAA;AAE9B;AAMO,SAAS,eAAe,MAAe,UAAsB,UAAU,MAAM;AAClF,QAAM,KAAK,MAAA;AACX,QAAM,cAAc,OAAO,QAAQ;AACnC,cAAY,UAAU;AAEtB,YAAU,MAAM;AACd,QAAI,CAAC,QAAQ,CAAC,QAAS;AAEvB,yBAAA;AACA,gBAAY,KAAK;AAAA,MACf;AAAA,MACA,UAAU,MAAM,YAAY,QAAA;AAAA,IAAQ,CACrC;AAED,WAAO,MAAM,kBAAkB,EAAE;AAAA,EACnC,GAAG,CAAC,SAAS,IAAI,IAAI,CAAC;AACxB;AAOO,SAAS,aAAa,QAAuB;AAClD,uBAAqB,WAAW,aAAa,WAAW;AAExD,YAAU,MAAM;AACd,QAAI,CAAC,OAAQ;AACb,kBAAc;AACd,SAAA;AACA,WAAO,MAAM;AACX,oBAAc;AACd,WAAA;AAAA,IACF;AAAA,EACF,GAAG,CAAC,MAAM,CAAC;AACb;AAUO,SAAS,oBAA4B;AAC1C,uBAAqB,WAAW,aAAa,WAAW;AACxD,QAAM,OACJ,MAAM,WAAW,IACb,OAAO,UACP,OAAO,SAAS,MAAM,SAAS,KAAK,OAAO,YAAY,OAAO;AACpE,MAAI,eAAe,EAAG,QAAO;AAC7B,SAAO,KAAK,IAAI,MAAM,OAAO,OAAO,OAAO,iBAAiB,OAAO,sBAAsB;AAC3F;"}
1
+ {"version":3,"file":"modalStack.js","sources":["../../src/overlay/modalStack.ts"],"sourcesContent":["import { useEffect, useId, useRef, useSyncExternalStore } from \"react\";\nimport { zIndex } from \"./zIndex\";\n\n// A process-wide stack of the currently open modals, topmost last. Modals mount\n// independently (no shared provider), so the stack lives at module scope and is\n// shared through useSyncExternalStore. It lets nested modals cooperate: only the\n// topmost reacts to Escape, and each renders above the one it opened over.\nconst stack: string[] = [];\nconst listeners = new Set<() => void>();\n// `dismissed` marks a layer whose onEscape already ran but whose close has not\n// committed yet, so a quick second Escape reaches the layer beneath it.\ntype EscapeLayer = { id: string; dismissed: boolean; onEscape: () => void };\nconst escapeStack: EscapeLayer[] = [];\nlet escapeDocument: Document | null = null;\n// Running guided tours. A tour dims the page from `zIndex.tour`, far above the\n// modal band, so floating content opened *during* a tour (the menu a step tells\n// the user to open) has to clear that dim or it renders invisibly underneath.\nlet tourLayers = 0;\n\nfunction emit() {\n for (const listener of listeners) listener();\n}\n\nfunction subscribe(listener: () => void) {\n listeners.add(listener);\n return () => {\n listeners.delete(listener);\n };\n}\n\n// The snapshot is the stack identity plus the tour-layer count; it only changes\n// when an entry is pushed or popped, so subscribers re-render exactly when their\n// position could have moved.\nfunction getSnapshot() {\n return `${tourLayers}:` + stack.join(\"\\u0000\");\n}\n\nfunction onEscapeKeyDown(event: KeyboardEvent) {\n if (\n event.defaultPrevented ||\n event.key !== \"Escape\" ||\n event.isComposing ||\n (event as KeyboardEvent & { keyCode?: number }).keyCode === 229\n ) {\n return;\n }\n\n const top = escapeStack.findLast((entry) => !entry.dismissed);\n if (!top) return;\n\n event.preventDefault();\n event.stopPropagation();\n event.stopImmediatePropagation();\n top.dismissed = true;\n top.onEscape();\n}\n\nfunction ensureEscapeListener() {\n if (escapeDocument || typeof document === \"undefined\") return;\n escapeDocument = document;\n escapeDocument.addEventListener(\"keydown\", onEscapeKeyDown);\n}\n\nfunction removeEscapeLayer(id: string) {\n const index = escapeStack.findIndex((entry) => entry.id === id);\n if (index !== -1) escapeStack.splice(index, 1);\n\n if (escapeStack.length === 0 && escapeDocument) {\n escapeDocument.removeEventListener(\"keydown\", onEscapeKeyDown);\n escapeDocument = null;\n }\n}\n\nexport type ModalStackPosition = {\n /** Whether this modal is the topmost open one and should own global affordances. */\n isTop: boolean;\n /** Zero-based depth in the stack; drives the stacking order of nested modals. */\n depth: number;\n};\n\n/**\n * Registers a modal in the global stack while `open`, returning its live\n * position. Used so a nested modal sits above its opener and only the topmost\n * modal closes on Escape.\n */\nexport function useModalStack(open: boolean): ModalStackPosition {\n const id = useId();\n useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n\n useEffect(() => {\n if (!open) return;\n stack.push(id);\n emit();\n return () => {\n const index = stack.indexOf(id);\n if (index !== -1) stack.splice(index, 1);\n emit();\n };\n }, [open, id]);\n\n const depth = stack.indexOf(id);\n return {\n isTop: depth !== -1 && depth === stack.length - 1,\n depth: depth === -1 ? 0 : depth,\n };\n}\n\n/**\n * Registers an Escape-closeable overlay while `open`. The topmost registered\n * layer owns Escape, so a keypress dismisses one dialog/menu layer at a time.\n */\nexport function useEscapeLayer(open: boolean, onEscape: () => void, enabled = true) {\n const id = useId();\n const onEscapeRef = useRef(onEscape);\n onEscapeRef.current = onEscape;\n const entryRef = useRef<EscapeLayer | null>(null);\n\n // A dismissed layer that re-rendered without closing owns Escape again.\n useEffect(() => {\n if (entryRef.current) entryRef.current.dismissed = false;\n });\n\n useEffect(() => {\n if (!open || !enabled) return;\n\n ensureEscapeListener();\n const entry: EscapeLayer = { id, dismissed: false, onEscape: () => onEscapeRef.current() };\n entryRef.current = entry;\n escapeStack.push(entry);\n\n return () => {\n entryRef.current = null;\n removeEscapeLayer(id);\n };\n }, [enabled, id, open]);\n}\n\n/**\n * Registers a running guided tour while `active`, so floating layers lift above\n * its dim. Symmetric with `useModalStack`, but a count rather than a stack: the\n * tour overlay does not nest.\n */\nexport function useTourLayer(active: boolean): void {\n useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n\n useEffect(() => {\n if (!active) return;\n tourLayers += 1;\n emit();\n return () => {\n tourLayers -= 1;\n emit();\n };\n }, [active]);\n}\n\n/**\n * z-index a floating layer (dropdown / combobox / tooltip / popover) should use\n * so it renders above any open modal — and below the next nested modal — or at\n * the popover floor when no modal is open. While a guided tour runs, the value\n * also clears the tour's dim and step card, so a step that says \"open this menu\"\n * shows the menu rather than hiding it under the overlay. Subscribes to the\n * modal stack so the value tracks modals and tours opening and closing.\n */\nexport function useFloatingZIndex(): number {\n useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n const base =\n stack.length === 0\n ? zIndex.popover\n : zIndex.modal + (stack.length - 1) * zIndex.modalStep + zIndex.popoverOverModalOffset;\n if (tourLayers === 0) return base;\n return Math.max(base, zIndex.tour + zIndex.tourCardOffset + zIndex.popoverOverModalOffset);\n}\n"],"names":[],"mappings":"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"}
@@ -2,19 +2,18 @@
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
3
  const jsxRuntime = require("react/jsx-runtime");
4
4
  const button = require("../components/button.cjs");
5
+ const ErrorDetails = require("../data/diagnostics/ErrorDetails.cjs");
5
6
  const Icon = require("../data/Icon.cjs");
6
- const utils = require("../lib/utils.cjs");
7
+ const operationErrorDiagnostics = require("./operationErrorDiagnostics.cjs");
7
8
  const UiPlay = require("../icons/components/UiPlay.cjs");
8
- const UiChevronRight = require("../icons/components/UiChevronRight.cjs");
9
9
  function InlineError({ title, error, className, runNow }) {
10
- const message = error instanceof Error ? error.message : String(error ?? "");
11
- const details = getErrorDetails(error);
12
- const hasDetails = Boolean(details.responseBody || details.status || details.url);
13
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: utils.cn("rounded-xl border border-dashed border-red-300 p-6 text-sm", className), children: [
14
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-center", children: [
15
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "font-medium text-red-600", children: title }),
16
- message && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1 text-muted-foreground", children: message }),
17
- runNow && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-3 flex justify-center", children: /* @__PURE__ */ jsxRuntime.jsxs(
10
+ return /* @__PURE__ */ jsxRuntime.jsx(
11
+ ErrorDetails.ErrorDetails,
12
+ {
13
+ title,
14
+ diagnostics: operationErrorDiagnostics.operationErrorDiagnostics(error),
15
+ ...className ? { className } : {},
16
+ actions: runNow && /* @__PURE__ */ jsxRuntime.jsxs(
18
17
  button.Button,
19
18
  {
20
19
  type: "button",
@@ -28,39 +27,9 @@ function InlineError({ title, error, className, runNow }) {
28
27
  "Run now"
29
28
  ]
30
29
  }
31
- ) })
32
- ] }),
33
- hasDetails && /* @__PURE__ */ jsxRuntime.jsxs("details", { className: "group mt-3", children: [
34
- /* @__PURE__ */ jsxRuntime.jsxs("summary", { className: "flex cursor-pointer items-center justify-center gap-1 text-xs text-muted-foreground hover:text-foreground", children: [
35
- /* @__PURE__ */ jsxRuntime.jsx(Icon.Icon, { icon: UiChevronRight.UiChevronRight, className: "transition-transform group-open:rotate-90" }),
36
- "More details"
37
- ] }),
38
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-2 space-y-2 text-left font-mono text-xs", children: [
39
- (details.method || details.url || details.status) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-muted-foreground", children: [
40
- details.method && /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
41
- details.method,
42
- " "
43
- ] }),
44
- details.url,
45
- details.status != null && /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
46
- " - ",
47
- details.status
48
- ] })
49
- ] }),
50
- details.responseBody && /* @__PURE__ */ jsxRuntime.jsx("pre", { className: "max-h-64 overflow-auto rounded-md bg-muted p-2 text-xs", children: details.responseBody })
51
- ] })
52
- ] })
53
- ] });
54
- }
55
- function getErrorDetails(error) {
56
- if (error == null || typeof error !== "object") return {};
57
- const record = error;
58
- const details = {};
59
- if (typeof record.method === "string") details.method = record.method;
60
- if (typeof record.url === "string") details.url = record.url;
61
- if (typeof record.status === "number") details.status = record.status;
62
- if (typeof record.responseBody === "string") details.responseBody = record.responseBody;
63
- return details;
30
+ )
31
+ }
32
+ );
64
33
  }
65
34
  exports.InlineError = InlineError;
66
35
  //# sourceMappingURL=InlineError.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"InlineError.cjs","sources":["../../src/rpc/InlineError.tsx"],"sourcesContent":["import { Button } from \"../components/button\";\nimport { Icon } from \"../data/Icon\";\nimport { UiChevronRight, UiPlay } from \"../icons\";\nimport { cn } from \"../lib/utils\";\n\nexport type InlineErrorProps = {\n title: string;\n error: unknown;\n className?: string;\n runNow?: {\n onClick: () => void;\n loading?: boolean;\n };\n};\n\ntype ErrorDetails = {\n method?: string;\n url?: string;\n status?: number;\n responseBody?: string;\n};\n\nexport function InlineError({ title, error, className, runNow }: InlineErrorProps) {\n const message = error instanceof Error ? error.message : String(error ?? \"\");\n const details = getErrorDetails(error);\n const hasDetails = Boolean(details.responseBody || details.status || details.url);\n\n return (\n <div className={cn(\"rounded-xl border border-dashed border-red-300 p-6 text-sm\", className)}>\n <div className=\"text-center\">\n <div className=\"font-medium text-red-600\">{title}</div>\n {message && <div className=\"mt-1 text-muted-foreground\">{message}</div>}\n {runNow && (\n <div className=\"mt-3 flex justify-center\">\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n onClick={runNow.onClick}\n loading={runNow.loading ?? false}\n loadingLabel={runNow.loading ? \"Running…\" : undefined}\n >\n <Icon icon={UiPlay} />\n Run now\n </Button>\n </div>\n )}\n </div>\n {hasDetails && (\n <details className=\"group mt-3\">\n <summary className=\"flex cursor-pointer items-center justify-center gap-1 text-xs text-muted-foreground hover:text-foreground\">\n <Icon icon={UiChevronRight} className=\"transition-transform group-open:rotate-90\" />\n More details\n </summary>\n <div className=\"mt-2 space-y-2 text-left font-mono text-xs\">\n {(details.method || details.url || details.status) && (\n <div className=\"text-muted-foreground\">\n {details.method && <span>{details.method} </span>}\n {details.url}\n {details.status != null && <span> - {details.status}</span>}\n </div>\n )}\n {details.responseBody && (\n <pre className=\"max-h-64 overflow-auto rounded-md bg-muted p-2 text-xs\">\n {details.responseBody}\n </pre>\n )}\n </div>\n </details>\n )}\n </div>\n );\n}\n\nfunction getErrorDetails(error: unknown): ErrorDetails {\n if (error == null || typeof error !== \"object\") return {};\n const record = error as Record<string, unknown>;\n const details: ErrorDetails = {};\n if (typeof record.method === \"string\") details.method = record.method;\n if (typeof record.url === \"string\") details.url = record.url;\n if (typeof record.status === \"number\") details.status = record.status;\n if (typeof record.responseBody === \"string\") details.responseBody = record.responseBody;\n return details;\n}\n"],"names":["cn","jsxs","jsx","Button","Icon","UiPlay","UiChevronRight"],"mappings":";;;;;;;;AAsBO,SAAS,YAAY,EAAE,OAAO,OAAO,WAAW,UAA4B;AACjF,QAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,SAAS,EAAE;AAC3E,QAAM,UAAU,gBAAgB,KAAK;AACrC,QAAM,aAAa,QAAQ,QAAQ,gBAAgB,QAAQ,UAAU,QAAQ,GAAG;AAEhF,yCACG,OAAA,EAAI,WAAWA,MAAAA,GAAG,8DAA8D,SAAS,GACxF,UAAA;AAAA,IAAAC,2BAAAA,KAAC,OAAA,EAAI,WAAU,eACb,UAAA;AAAA,MAAAC,2BAAAA,IAAC,OAAA,EAAI,WAAU,4BAA4B,UAAA,OAAM;AAAA,MAChD,WAAWA,2BAAAA,IAAC,OAAA,EAAI,WAAU,8BAA8B,UAAA,SAAQ;AAAA,MAChE,UACCA,2BAAAA,IAAC,OAAA,EAAI,WAAU,4BACb,UAAAD,2BAAAA;AAAAA,QAACE,OAAAA;AAAAA,QAAA;AAAA,UACC,MAAK;AAAA,UACL,SAAQ;AAAA,UACR,MAAK;AAAA,UACL,SAAS,OAAO;AAAA,UAChB,SAAS,OAAO,WAAW;AAAA,UAC3B,cAAc,OAAO,UAAU,aAAa;AAAA,UAE5C,UAAA;AAAA,YAAAD,2BAAAA,IAACE,KAAAA,MAAA,EAAK,MAAMC,OAAAA,OAAA,CAAQ;AAAA,YAAE;AAAA,UAAA;AAAA,QAAA;AAAA,MAAA,EAExB,CACF;AAAA,IAAA,GAEJ;AAAA,IACC,cACCJ,2BAAAA,KAAC,WAAA,EAAQ,WAAU,cACjB,UAAA;AAAA,MAAAA,2BAAAA,KAAC,WAAA,EAAQ,WAAU,6GACjB,UAAA;AAAA,QAAAC,2BAAAA,IAACE,KAAAA,MAAA,EAAK,MAAME,eAAAA,gBAAgB,WAAU,6CAA4C;AAAA,QAAE;AAAA,MAAA,GAEtF;AAAA,MACAL,2BAAAA,KAAC,OAAA,EAAI,WAAU,8CACX,UAAA;AAAA,SAAA,QAAQ,UAAU,QAAQ,OAAO,QAAQ,WACzCA,2BAAAA,KAAC,OAAA,EAAI,WAAU,yBACZ,UAAA;AAAA,UAAA,QAAQ,0CAAW,QAAA,EAAM,UAAA;AAAA,YAAA,QAAQ;AAAA,YAAO;AAAA,UAAA,GAAC;AAAA,UACzC,QAAQ;AAAA,UACR,QAAQ,UAAU,QAAQA,2BAAAA,KAAC,QAAA,EAAK,UAAA;AAAA,YAAA;AAAA,YAAI,QAAQ;AAAA,UAAA,EAAA,CAAO;AAAA,QAAA,GACtD;AAAA,QAED,QAAQ,gBACPC,2BAAAA,IAAC,SAAI,WAAU,0DACZ,kBAAQ,aAAA,CACX;AAAA,MAAA,EAAA,CAEJ;AAAA,IAAA,EAAA,CACF;AAAA,EAAA,GAEJ;AAEJ;AAEA,SAAS,gBAAgB,OAA8B;AACrD,MAAI,SAAS,QAAQ,OAAO,UAAU,iBAAiB,CAAA;AACvD,QAAM,SAAS;AACf,QAAM,UAAwB,CAAA;AAC9B,MAAI,OAAO,OAAO,WAAW,SAAU,SAAQ,SAAS,OAAO;AAC/D,MAAI,OAAO,OAAO,QAAQ,SAAU,SAAQ,MAAM,OAAO;AACzD,MAAI,OAAO,OAAO,WAAW,SAAU,SAAQ,SAAS,OAAO;AAC/D,MAAI,OAAO,OAAO,iBAAiB,SAAU,SAAQ,eAAe,OAAO;AAC3E,SAAO;AACT;;"}
1
+ {"version":3,"file":"InlineError.cjs","sources":["../../src/rpc/InlineError.tsx"],"sourcesContent":["import { Button } from \"../components/button\";\nimport { ErrorDetails } from \"../data/diagnostics/ErrorDetails\";\nimport { Icon } from \"../data/Icon\";\nimport { UiPlay } from \"../icons\";\nimport { operationErrorDiagnostics } from \"./operationErrorDiagnostics\";\n\nexport type InlineErrorProps = {\n title: string;\n error: unknown;\n className?: string;\n runNow?: {\n onClick: () => void;\n loading?: boolean;\n };\n};\n\nexport function InlineError({ title, error, className, runNow }: InlineErrorProps) {\n return (\n <ErrorDetails\n title={title}\n diagnostics={operationErrorDiagnostics(error)}\n {...(className ? { className } : {})}\n actions={\n runNow && (\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n onClick={runNow.onClick}\n loading={runNow.loading ?? false}\n loadingLabel={runNow.loading ? \"Running…\" : undefined}\n >\n <Icon icon={UiPlay} />\n Run now\n </Button>\n )\n }\n />\n );\n}\n"],"names":["jsx","ErrorDetails","operationErrorDiagnostics","jsxs","Button","Icon","UiPlay"],"mappings":";;;;;;;;AAgBO,SAAS,YAAY,EAAE,OAAO,OAAO,WAAW,UAA4B;AACjF,SACEA,2BAAAA;AAAAA,IAACC,aAAAA;AAAAA,IAAA;AAAA,MACC;AAAA,MACA,aAAaC,0BAAAA,0BAA0B,KAAK;AAAA,MAC3C,GAAI,YAAY,EAAE,UAAA,IAAc,CAAA;AAAA,MACjC,SACE,UACEC,2BAAAA;AAAAA,QAACC,OAAAA;AAAAA,QAAA;AAAA,UACC,MAAK;AAAA,UACL,SAAQ;AAAA,UACR,MAAK;AAAA,UACL,SAAS,OAAO;AAAA,UAChB,SAAS,OAAO,WAAW;AAAA,UAC3B,cAAc,OAAO,UAAU,aAAa;AAAA,UAE5C,UAAA;AAAA,YAAAJ,2BAAAA,IAACK,KAAAA,MAAA,EAAK,MAAMC,OAAAA,OAAA,CAAQ;AAAA,YAAE;AAAA,UAAA;AAAA,QAAA;AAAA,MAAA;AAAA,IAExB;AAAA,EAAA;AAKV;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"InlineError.d.ts","sourceRoot":"","sources":["../../src/rpc/InlineError.tsx"],"names":[],"mappings":"AAKA,MAAM,MAAM,gBAAgB,GAAG;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,OAAO,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE;QACP,OAAO,EAAE,MAAM,IAAI,CAAC;QACpB,OAAO,CAAC,EAAE,OAAO,CAAC;KACnB,CAAC;CACH,CAAC;AASF,wBAAgB,WAAW,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,EAAE,gBAAgB,+BAkDhF"}
1
+ {"version":3,"file":"InlineError.d.ts","sourceRoot":"","sources":["../../src/rpc/InlineError.tsx"],"names":[],"mappings":"AAMA,MAAM,MAAM,gBAAgB,GAAG;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,OAAO,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE;QACP,OAAO,EAAE,MAAM,IAAI,CAAC;QACpB,OAAO,CAAC,EAAE,OAAO,CAAC;KACnB,CAAC;CACH,CAAC;AAEF,wBAAgB,WAAW,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,EAAE,gBAAgB,+BAuBhF"}
@@ -1,18 +1,17 @@
1
- import { jsxs, jsx } from "react/jsx-runtime";
1
+ import { jsx, jsxs } from "react/jsx-runtime";
2
2
  import { Button } from "../components/button.js";
3
+ import { ErrorDetails } from "../data/diagnostics/ErrorDetails.js";
3
4
  import { Icon } from "../data/Icon.js";
4
- import { cn } from "../lib/utils.js";
5
+ import { operationErrorDiagnostics } from "./operationErrorDiagnostics.js";
5
6
  import { UiPlay } from "../icons/components/UiPlay.js";
6
- import { UiChevronRight } from "../icons/components/UiChevronRight.js";
7
7
  function InlineError({ title, error, className, runNow }) {
8
- const message = error instanceof Error ? error.message : String(error ?? "");
9
- const details = getErrorDetails(error);
10
- const hasDetails = Boolean(details.responseBody || details.status || details.url);
11
- return /* @__PURE__ */ jsxs("div", { className: cn("rounded-xl border border-dashed border-red-300 p-6 text-sm", className), children: [
12
- /* @__PURE__ */ jsxs("div", { className: "text-center", children: [
13
- /* @__PURE__ */ jsx("div", { className: "font-medium text-red-600", children: title }),
14
- message && /* @__PURE__ */ jsx("div", { className: "mt-1 text-muted-foreground", children: message }),
15
- runNow && /* @__PURE__ */ jsx("div", { className: "mt-3 flex justify-center", children: /* @__PURE__ */ jsxs(
8
+ return /* @__PURE__ */ jsx(
9
+ ErrorDetails,
10
+ {
11
+ title,
12
+ diagnostics: operationErrorDiagnostics(error),
13
+ ...className ? { className } : {},
14
+ actions: runNow && /* @__PURE__ */ jsxs(
16
15
  Button,
17
16
  {
18
17
  type: "button",
@@ -26,39 +25,9 @@ function InlineError({ title, error, className, runNow }) {
26
25
  "Run now"
27
26
  ]
28
27
  }
29
- ) })
30
- ] }),
31
- hasDetails && /* @__PURE__ */ jsxs("details", { className: "group mt-3", children: [
32
- /* @__PURE__ */ jsxs("summary", { className: "flex cursor-pointer items-center justify-center gap-1 text-xs text-muted-foreground hover:text-foreground", children: [
33
- /* @__PURE__ */ jsx(Icon, { icon: UiChevronRight, className: "transition-transform group-open:rotate-90" }),
34
- "More details"
35
- ] }),
36
- /* @__PURE__ */ jsxs("div", { className: "mt-2 space-y-2 text-left font-mono text-xs", children: [
37
- (details.method || details.url || details.status) && /* @__PURE__ */ jsxs("div", { className: "text-muted-foreground", children: [
38
- details.method && /* @__PURE__ */ jsxs("span", { children: [
39
- details.method,
40
- " "
41
- ] }),
42
- details.url,
43
- details.status != null && /* @__PURE__ */ jsxs("span", { children: [
44
- " - ",
45
- details.status
46
- ] })
47
- ] }),
48
- details.responseBody && /* @__PURE__ */ jsx("pre", { className: "max-h-64 overflow-auto rounded-md bg-muted p-2 text-xs", children: details.responseBody })
49
- ] })
50
- ] })
51
- ] });
52
- }
53
- function getErrorDetails(error) {
54
- if (error == null || typeof error !== "object") return {};
55
- const record = error;
56
- const details = {};
57
- if (typeof record.method === "string") details.method = record.method;
58
- if (typeof record.url === "string") details.url = record.url;
59
- if (typeof record.status === "number") details.status = record.status;
60
- if (typeof record.responseBody === "string") details.responseBody = record.responseBody;
61
- return details;
28
+ )
29
+ }
30
+ );
62
31
  }
63
32
  export {
64
33
  InlineError
@@ -1 +1 @@
1
- {"version":3,"file":"InlineError.js","sources":["../../src/rpc/InlineError.tsx"],"sourcesContent":["import { Button } from \"../components/button\";\nimport { Icon } from \"../data/Icon\";\nimport { UiChevronRight, UiPlay } from \"../icons\";\nimport { cn } from \"../lib/utils\";\n\nexport type InlineErrorProps = {\n title: string;\n error: unknown;\n className?: string;\n runNow?: {\n onClick: () => void;\n loading?: boolean;\n };\n};\n\ntype ErrorDetails = {\n method?: string;\n url?: string;\n status?: number;\n responseBody?: string;\n};\n\nexport function InlineError({ title, error, className, runNow }: InlineErrorProps) {\n const message = error instanceof Error ? error.message : String(error ?? \"\");\n const details = getErrorDetails(error);\n const hasDetails = Boolean(details.responseBody || details.status || details.url);\n\n return (\n <div className={cn(\"rounded-xl border border-dashed border-red-300 p-6 text-sm\", className)}>\n <div className=\"text-center\">\n <div className=\"font-medium text-red-600\">{title}</div>\n {message && <div className=\"mt-1 text-muted-foreground\">{message}</div>}\n {runNow && (\n <div className=\"mt-3 flex justify-center\">\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n onClick={runNow.onClick}\n loading={runNow.loading ?? false}\n loadingLabel={runNow.loading ? \"Running…\" : undefined}\n >\n <Icon icon={UiPlay} />\n Run now\n </Button>\n </div>\n )}\n </div>\n {hasDetails && (\n <details className=\"group mt-3\">\n <summary className=\"flex cursor-pointer items-center justify-center gap-1 text-xs text-muted-foreground hover:text-foreground\">\n <Icon icon={UiChevronRight} className=\"transition-transform group-open:rotate-90\" />\n More details\n </summary>\n <div className=\"mt-2 space-y-2 text-left font-mono text-xs\">\n {(details.method || details.url || details.status) && (\n <div className=\"text-muted-foreground\">\n {details.method && <span>{details.method} </span>}\n {details.url}\n {details.status != null && <span> - {details.status}</span>}\n </div>\n )}\n {details.responseBody && (\n <pre className=\"max-h-64 overflow-auto rounded-md bg-muted p-2 text-xs\">\n {details.responseBody}\n </pre>\n )}\n </div>\n </details>\n )}\n </div>\n );\n}\n\nfunction getErrorDetails(error: unknown): ErrorDetails {\n if (error == null || typeof error !== \"object\") return {};\n const record = error as Record<string, unknown>;\n const details: ErrorDetails = {};\n if (typeof record.method === \"string\") details.method = record.method;\n if (typeof record.url === \"string\") details.url = record.url;\n if (typeof record.status === \"number\") details.status = record.status;\n if (typeof record.responseBody === \"string\") details.responseBody = record.responseBody;\n return details;\n}\n"],"names":[],"mappings":";;;;;;AAsBO,SAAS,YAAY,EAAE,OAAO,OAAO,WAAW,UAA4B;AACjF,QAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,SAAS,EAAE;AAC3E,QAAM,UAAU,gBAAgB,KAAK;AACrC,QAAM,aAAa,QAAQ,QAAQ,gBAAgB,QAAQ,UAAU,QAAQ,GAAG;AAEhF,8BACG,OAAA,EAAI,WAAW,GAAG,8DAA8D,SAAS,GACxF,UAAA;AAAA,IAAA,qBAAC,OAAA,EAAI,WAAU,eACb,UAAA;AAAA,MAAA,oBAAC,OAAA,EAAI,WAAU,4BAA4B,UAAA,OAAM;AAAA,MAChD,WAAW,oBAAC,OAAA,EAAI,WAAU,8BAA8B,UAAA,SAAQ;AAAA,MAChE,UACC,oBAAC,OAAA,EAAI,WAAU,4BACb,UAAA;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,MAAK;AAAA,UACL,SAAQ;AAAA,UACR,MAAK;AAAA,UACL,SAAS,OAAO;AAAA,UAChB,SAAS,OAAO,WAAW;AAAA,UAC3B,cAAc,OAAO,UAAU,aAAa;AAAA,UAE5C,UAAA;AAAA,YAAA,oBAAC,MAAA,EAAK,MAAM,OAAA,CAAQ;AAAA,YAAE;AAAA,UAAA;AAAA,QAAA;AAAA,MAAA,EAExB,CACF;AAAA,IAAA,GAEJ;AAAA,IACC,cACC,qBAAC,WAAA,EAAQ,WAAU,cACjB,UAAA;AAAA,MAAA,qBAAC,WAAA,EAAQ,WAAU,6GACjB,UAAA;AAAA,QAAA,oBAAC,MAAA,EAAK,MAAM,gBAAgB,WAAU,6CAA4C;AAAA,QAAE;AAAA,MAAA,GAEtF;AAAA,MACA,qBAAC,OAAA,EAAI,WAAU,8CACX,UAAA;AAAA,SAAA,QAAQ,UAAU,QAAQ,OAAO,QAAQ,WACzC,qBAAC,OAAA,EAAI,WAAU,yBACZ,UAAA;AAAA,UAAA,QAAQ,+BAAW,QAAA,EAAM,UAAA;AAAA,YAAA,QAAQ;AAAA,YAAO;AAAA,UAAA,GAAC;AAAA,UACzC,QAAQ;AAAA,UACR,QAAQ,UAAU,QAAQ,qBAAC,QAAA,EAAK,UAAA;AAAA,YAAA;AAAA,YAAI,QAAQ;AAAA,UAAA,EAAA,CAAO;AAAA,QAAA,GACtD;AAAA,QAED,QAAQ,gBACP,oBAAC,SAAI,WAAU,0DACZ,kBAAQ,aAAA,CACX;AAAA,MAAA,EAAA,CAEJ;AAAA,IAAA,EAAA,CACF;AAAA,EAAA,GAEJ;AAEJ;AAEA,SAAS,gBAAgB,OAA8B;AACrD,MAAI,SAAS,QAAQ,OAAO,UAAU,iBAAiB,CAAA;AACvD,QAAM,SAAS;AACf,QAAM,UAAwB,CAAA;AAC9B,MAAI,OAAO,OAAO,WAAW,SAAU,SAAQ,SAAS,OAAO;AAC/D,MAAI,OAAO,OAAO,QAAQ,SAAU,SAAQ,MAAM,OAAO;AACzD,MAAI,OAAO,OAAO,WAAW,SAAU,SAAQ,SAAS,OAAO;AAC/D,MAAI,OAAO,OAAO,iBAAiB,SAAU,SAAQ,eAAe,OAAO;AAC3E,SAAO;AACT;"}
1
+ {"version":3,"file":"InlineError.js","sources":["../../src/rpc/InlineError.tsx"],"sourcesContent":["import { Button } from \"../components/button\";\nimport { ErrorDetails } from \"../data/diagnostics/ErrorDetails\";\nimport { Icon } from \"../data/Icon\";\nimport { UiPlay } from \"../icons\";\nimport { operationErrorDiagnostics } from \"./operationErrorDiagnostics\";\n\nexport type InlineErrorProps = {\n title: string;\n error: unknown;\n className?: string;\n runNow?: {\n onClick: () => void;\n loading?: boolean;\n };\n};\n\nexport function InlineError({ title, error, className, runNow }: InlineErrorProps) {\n return (\n <ErrorDetails\n title={title}\n diagnostics={operationErrorDiagnostics(error)}\n {...(className ? { className } : {})}\n actions={\n runNow && (\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n onClick={runNow.onClick}\n loading={runNow.loading ?? false}\n loadingLabel={runNow.loading ? \"Running…\" : undefined}\n >\n <Icon icon={UiPlay} />\n Run now\n </Button>\n )\n }\n />\n );\n}\n"],"names":[],"mappings":";;;;;;AAgBO,SAAS,YAAY,EAAE,OAAO,OAAO,WAAW,UAA4B;AACjF,SACE;AAAA,IAAC;AAAA,IAAA;AAAA,MACC;AAAA,MACA,aAAa,0BAA0B,KAAK;AAAA,MAC3C,GAAI,YAAY,EAAE,UAAA,IAAc,CAAA;AAAA,MACjC,SACE,UACE;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,MAAK;AAAA,UACL,SAAQ;AAAA,UACR,MAAK;AAAA,UACL,SAAS,OAAO;AAAA,UAChB,SAAS,OAAO,WAAW;AAAA,UAC3B,cAAc,OAAO,UAAU,aAAa;AAAA,UAE5C,UAAA;AAAA,YAAA,oBAAC,MAAA,EAAK,MAAM,OAAA,CAAQ;AAAA,YAAE;AAAA,UAAA;AAAA,QAAA;AAAA,MAAA;AAAA,IAExB;AAAA,EAAA;AAKV;"}
@@ -3,6 +3,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
3
  const jsxRuntime = require("react/jsx-runtime");
4
4
  const react = require("react");
5
5
  const button = require("../components/button.cjs");
6
+ const Combobox = require("../components/Combobox.cjs");
6
7
  const CopyButton = require("../components/CopyButton.cjs");
7
8
  const Field = require("../components/Field.cjs");
8
9
  const InputField = require("../components/InputField.cjs");
@@ -15,7 +16,18 @@ const InlineError = require("./InlineError.cjs");
15
16
  const OperationPicker = require("./OperationPicker.cjs");
16
17
  function OperationScheduleDialog(_props) {
17
18
  var _a, _b, _c, _d;
18
- const { open, operations, schedule, cli, onClose, onSave, onRunNow } = _props;
19
+ const {
20
+ open,
21
+ operations,
22
+ schedule,
23
+ cli,
24
+ targetOptions,
25
+ defaultTargets,
26
+ targetLabel = "Targets",
27
+ onClose,
28
+ onSave,
29
+ onRunNow
30
+ } = _props;
19
31
  const [input, setInput] = react.useState(
20
32
  operationScheduleModel.newOperationScheduleInput
21
33
  );
@@ -25,16 +37,24 @@ function OperationScheduleDialog(_props) {
25
37
  react.useEffect(() => {
26
38
  if (!open) return;
27
39
  setInput(
28
- schedule ? operationScheduleModel.scheduleToInput(schedule) : operationScheduleModel.newOperationScheduleInput()
40
+ schedule ? operationScheduleModel.scheduleToInput(schedule) : {
41
+ ...operationScheduleModel.newOperationScheduleInput(),
42
+ targets: [...defaultTargets ?? []]
43
+ }
29
44
  );
30
45
  setError(void 0);
31
46
  setConfirmingRun(false);
32
- }, [open, schedule]);
47
+ }, [open, schedule, defaultTargets]);
33
48
  const operation = operationScheduleModel.operationByID(operations, input.operationId);
34
49
  const schema = operationScheduleModel.operationInputSchema(operation);
35
50
  const suggestions = ((_b = (_a = operation == null ? void 0 : operation.operation["x-clicky"]) == null ? void 0 : _a.schedule) == null ? void 0 : _b.suggestions) ?? [];
36
51
  const destructive = ((_d = (_c = operation == null ? void 0 : operation.operation["x-clicky"]) == null ? void 0 : _c.toolHints) == null ? void 0 : _d.destructiveHint) === true;
37
- const cliCommand = operationCliCommand.operationCLICommand(operation, input.args, cli);
52
+ const cliCommand = (cli == null ? void 0 : cli.targetFlag) ? input.targets.map(
53
+ (target) => operationCliCommand.operationCLICommand(operation, input.args, {
54
+ ...cli,
55
+ globalFlags: { ...cli.globalFlags, [cli.targetFlag]: target }
56
+ })
57
+ ).join("\n") : operationCliCommand.operationCLICommand(operation, input.args, cli);
38
58
  const selectOperation = (operationId) => {
39
59
  const selected = operationScheduleModel.operationByID(operations, operationId);
40
60
  setInput((current) => {
@@ -64,7 +84,11 @@ function OperationScheduleDialog(_props) {
64
84
  setPending("run");
65
85
  setError(void 0);
66
86
  try {
67
- await onRunNow({ operationId: input.operationId, args: input.args });
87
+ await onRunNow({
88
+ operationId: input.operationId,
89
+ args: input.args,
90
+ targets: input.targets
91
+ });
68
92
  setConfirmingRun(false);
69
93
  onClose();
70
94
  } catch (nextError) {
@@ -75,9 +99,9 @@ function OperationScheduleDialog(_props) {
75
99
  }
76
100
  };
77
101
  const canSave = Boolean(
78
- input.name.trim() && input.operationId && input.cron.trim()
102
+ input.name.trim() && input.operationId && input.cron.trim() && input.targets.length
79
103
  );
80
- const canRun = Boolean(input.operationId);
104
+ const canRun = Boolean(input.operationId && input.targets.length);
81
105
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
82
106
  /* @__PURE__ */ jsxRuntime.jsx(
83
107
  Modal.Modal,
@@ -111,6 +135,28 @@ function OperationScheduleDialog(_props) {
111
135
  )
112
136
  ] }),
113
137
  children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-5", children: [
138
+ /* @__PURE__ */ jsxRuntime.jsx(
139
+ Field.Field,
140
+ {
141
+ label: targetLabel,
142
+ htmlFor: "operation-schedule-targets",
143
+ required: true,
144
+ children: /* @__PURE__ */ jsxRuntime.jsx(
145
+ Combobox.Combobox,
146
+ {
147
+ id: "operation-schedule-targets",
148
+ multiple: true,
149
+ variant: "tags",
150
+ ariaLabel: targetLabel,
151
+ ariaRequired: true,
152
+ allowCustomValue: false,
153
+ options: targetOptions,
154
+ value: input.targets,
155
+ onChange: (targets) => setInput({ ...input, targets })
156
+ }
157
+ )
158
+ }
159
+ ),
114
160
  /* @__PURE__ */ jsxRuntime.jsx(
115
161
  Field.Field,
116
162
  {
@@ -152,7 +198,7 @@ function OperationScheduleDialog(_props) {
152
198
  cliCommand ? /* @__PURE__ */ jsxRuntime.jsxs("section", { className: "space-y-1", children: [
153
199
  /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-sm font-semibold", children: "Equivalent CLI command" }),
154
200
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 rounded-md border bg-muted/30 px-3 py-2", children: [
155
- /* @__PURE__ */ jsxRuntime.jsx("code", { className: "min-w-0 flex-1 overflow-x-auto whitespace-nowrap text-xs", children: cliCommand }),
201
+ /* @__PURE__ */ jsxRuntime.jsx("code", { className: "min-w-0 flex-1 overflow-x-auto whitespace-pre text-xs", children: cliCommand }),
156
202
  /* @__PURE__ */ jsxRuntime.jsx(CopyButton.CopyButton, { value: cliCommand, label: "Copy CLI command" })
157
203
  ] })
158
204
  ] }) : null,
@@ -170,7 +216,7 @@ function OperationScheduleDialog(_props) {
170
216
  ] })
171
217
  }
172
218
  ),
173
- /* @__PURE__ */ jsxRuntime.jsx(
219
+ /* @__PURE__ */ jsxRuntime.jsxs(
174
220
  Modal.Modal,
175
221
  {
176
222
  open: confirmingRun,
@@ -198,7 +244,14 @@ function OperationScheduleDialog(_props) {
198
244
  }
199
245
  )
200
246
  ] }),
201
- children: /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground", children: "This runs the configured operation once without creating or changing a recurring schedule." })
247
+ children: [
248
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground", children: "This runs the configured operation once without creating or changing a recurring schedule." }),
249
+ /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "mt-2 text-sm", children: [
250
+ targetLabel,
251
+ ": ",
252
+ input.targets.join(", ")
253
+ ] })
254
+ ]
202
255
  }
203
256
  )
204
257
  ] });