@flanksource/clicky-ui 0.3.44 → 0.3.46

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 (537) hide show
  1. package/README.md +24 -0
  2. package/dist/ai.cjs +4 -2
  3. package/dist/ai.cjs.map +1 -1
  4. package/dist/ai.js +3 -1
  5. package/dist/components/MdxEditorField.cjs +40 -22
  6. package/dist/components/MdxEditorField.cjs.map +1 -1
  7. package/dist/components/MdxEditorField.d.ts.map +1 -1
  8. package/dist/components/MdxEditorField.js +41 -23
  9. package/dist/components/MdxEditorField.js.map +1 -1
  10. package/dist/components/json-schema-form-item-summary.cjs +6 -1
  11. package/dist/components/json-schema-form-item-summary.cjs.map +1 -1
  12. package/dist/components/json-schema-form-item-summary.d.ts.map +1 -1
  13. package/dist/components/json-schema-form-item-summary.js +6 -1
  14. package/dist/components/json-schema-form-item-summary.js.map +1 -1
  15. package/dist/data/AccessMark.cjs +23 -0
  16. package/dist/data/AccessMark.cjs.map +1 -0
  17. package/dist/data/AccessMark.d.ts +11 -0
  18. package/dist/data/AccessMark.d.ts.map +1 -0
  19. package/dist/data/AccessMark.js +23 -0
  20. package/dist/data/AccessMark.js.map +1 -0
  21. package/dist/data/CodeBlock.cjs +3 -2
  22. package/dist/data/CodeBlock.cjs.map +1 -1
  23. package/dist/data/CodeBlock.d.ts +3 -1
  24. package/dist/data/CodeBlock.d.ts.map +1 -1
  25. package/dist/data/CodeBlock.js +3 -2
  26. package/dist/data/CodeBlock.js.map +1 -1
  27. package/dist/data/CodeDiff.cjs +116 -23
  28. package/dist/data/CodeDiff.cjs.map +1 -1
  29. package/dist/data/CodeDiff.d.ts +26 -0
  30. package/dist/data/CodeDiff.d.ts.map +1 -1
  31. package/dist/data/CodeDiff.js +116 -23
  32. package/dist/data/CodeDiff.js.map +1 -1
  33. package/dist/data/GraphDiagram.cjs +75 -11
  34. package/dist/data/GraphDiagram.cjs.map +1 -1
  35. package/dist/data/GraphDiagram.d.ts +17 -2
  36. package/dist/data/GraphDiagram.d.ts.map +1 -1
  37. package/dist/data/GraphDiagram.js +76 -12
  38. package/dist/data/GraphDiagram.js.map +1 -1
  39. package/dist/data/GraphDiagramGroups.cjs +100 -0
  40. package/dist/data/GraphDiagramGroups.cjs.map +1 -0
  41. package/dist/data/GraphDiagramGroups.d.ts +24 -0
  42. package/dist/data/GraphDiagramGroups.d.ts.map +1 -0
  43. package/dist/data/GraphDiagramGroups.js +100 -0
  44. package/dist/data/GraphDiagramGroups.js.map +1 -0
  45. package/dist/data/GraphDiagramNodes.cjs +46 -51
  46. package/dist/data/GraphDiagramNodes.cjs.map +1 -1
  47. package/dist/data/GraphDiagramNodes.d.ts +8 -9
  48. package/dist/data/GraphDiagramNodes.d.ts.map +1 -1
  49. package/dist/data/GraphDiagramNodes.js +46 -51
  50. package/dist/data/GraphDiagramNodes.js.map +1 -1
  51. package/dist/data/JsonView.cjs +118 -49
  52. package/dist/data/JsonView.cjs.map +1 -1
  53. package/dist/data/JsonView.d.ts +13 -10
  54. package/dist/data/JsonView.d.ts.map +1 -1
  55. package/dist/data/JsonView.js +118 -49
  56. package/dist/data/JsonView.js.map +1 -1
  57. package/dist/data/MarkdownEditor.cjs +2 -2
  58. package/dist/data/MarkdownEditor.cjs.map +1 -1
  59. package/dist/data/MarkdownEditor.js +2 -2
  60. package/dist/data/MarkdownEditor.js.map +1 -1
  61. package/dist/data/TreeNode.cjs +1 -1
  62. package/dist/data/TreeNode.cjs.map +1 -1
  63. package/dist/data/TreeNode.d.ts.map +1 -1
  64. package/dist/data/TreeNode.js +1 -1
  65. package/dist/data/TreeNode.js.map +1 -1
  66. package/dist/data/ai/AdvancedChatConfig.cjs +90 -249
  67. package/dist/data/ai/AdvancedChatConfig.cjs.map +1 -1
  68. package/dist/data/ai/AdvancedChatConfig.d.ts +2 -5
  69. package/dist/data/ai/AdvancedChatConfig.d.ts.map +1 -1
  70. package/dist/data/ai/AdvancedChatConfig.js +91 -250
  71. package/dist/data/ai/AdvancedChatConfig.js.map +1 -1
  72. package/dist/data/ai/ChatButton.cjs +2 -0
  73. package/dist/data/ai/ChatButton.cjs.map +1 -1
  74. package/dist/data/ai/ChatButton.d.ts +1 -1
  75. package/dist/data/ai/ChatButton.d.ts.map +1 -1
  76. package/dist/data/ai/ChatButton.js +2 -0
  77. package/dist/data/ai/ChatButton.js.map +1 -1
  78. package/dist/data/ai/ChatFab.cjs +5 -1
  79. package/dist/data/ai/ChatFab.cjs.map +1 -1
  80. package/dist/data/ai/ChatFab.d.ts +5 -1
  81. package/dist/data/ai/ChatFab.d.ts.map +1 -1
  82. package/dist/data/ai/ChatFab.js +5 -1
  83. package/dist/data/ai/ChatFab.js.map +1 -1
  84. package/dist/data/ai/ChatWindow.cjs +2 -8
  85. package/dist/data/ai/ChatWindow.cjs.map +1 -1
  86. package/dist/data/ai/ChatWindow.d.ts.map +1 -1
  87. package/dist/data/ai/ChatWindow.js +2 -8
  88. package/dist/data/ai/ChatWindow.js.map +1 -1
  89. package/dist/data/ai/ChatWindow.runtime.cjs +0 -5
  90. package/dist/data/ai/ChatWindow.runtime.cjs.map +1 -1
  91. package/dist/data/ai/ChatWindow.runtime.d.ts +0 -2
  92. package/dist/data/ai/ChatWindow.runtime.d.ts.map +1 -1
  93. package/dist/data/ai/ChatWindow.runtime.js +0 -5
  94. package/dist/data/ai/ChatWindow.runtime.js.map +1 -1
  95. package/dist/data/ai/PromptRunEditor/runtimeActions.cjs +2 -2
  96. package/dist/data/ai/PromptRunEditor/runtimeActions.cjs.map +1 -1
  97. package/dist/data/ai/PromptRunEditor/runtimeActions.d.ts.map +1 -1
  98. package/dist/data/ai/PromptRunEditor/runtimeActions.js +2 -2
  99. package/dist/data/ai/PromptRunEditor/runtimeActions.js.map +1 -1
  100. package/dist/data/ai/SessionInspector.approvals.cjs +3 -6
  101. package/dist/data/ai/SessionInspector.approvals.cjs.map +1 -1
  102. package/dist/data/ai/SessionInspector.approvals.js +3 -6
  103. package/dist/data/ai/SessionInspector.approvals.js.map +1 -1
  104. package/dist/data/ai/SessionViewer.cjs +13 -4
  105. package/dist/data/ai/SessionViewer.cjs.map +1 -1
  106. package/dist/data/ai/SessionViewer.d.ts +5 -1
  107. package/dist/data/ai/SessionViewer.d.ts.map +1 -1
  108. package/dist/data/ai/SessionViewer.header.cjs +1 -1
  109. package/dist/data/ai/SessionViewer.header.cjs.map +1 -1
  110. package/dist/data/ai/SessionViewer.header.js +1 -1
  111. package/dist/data/ai/SessionViewer.header.js.map +1 -1
  112. package/dist/data/ai/SessionViewer.js +13 -4
  113. package/dist/data/ai/SessionViewer.js.map +1 -1
  114. package/dist/data/ai/SessionViewer.model.cjs +2 -0
  115. package/dist/data/ai/SessionViewer.model.cjs.map +1 -1
  116. package/dist/data/ai/SessionViewer.model.d.ts +1 -0
  117. package/dist/data/ai/SessionViewer.model.d.ts.map +1 -1
  118. package/dist/data/ai/SessionViewer.model.js +2 -0
  119. package/dist/data/ai/SessionViewer.model.js.map +1 -1
  120. package/dist/data/ai/SessionViewer.rows.cjs +41 -27
  121. package/dist/data/ai/SessionViewer.rows.cjs.map +1 -1
  122. package/dist/data/ai/SessionViewer.rows.d.ts +4 -2
  123. package/dist/data/ai/SessionViewer.rows.d.ts.map +1 -1
  124. package/dist/data/ai/SessionViewer.rows.js +41 -27
  125. package/dist/data/ai/SessionViewer.rows.js.map +1 -1
  126. package/dist/data/ai/SessionViewer.tokens.cjs +35 -0
  127. package/dist/data/ai/SessionViewer.tokens.cjs.map +1 -0
  128. package/dist/data/ai/SessionViewer.tokens.d.ts +5 -0
  129. package/dist/data/ai/SessionViewer.tokens.d.ts.map +1 -0
  130. package/dist/data/ai/SessionViewer.tokens.js +35 -0
  131. package/dist/data/ai/SessionViewer.tokens.js.map +1 -0
  132. package/dist/data/ai/SessionViewer.tool-cost.cjs +128 -0
  133. package/dist/data/ai/SessionViewer.tool-cost.cjs.map +1 -0
  134. package/dist/data/ai/SessionViewer.tool-cost.d.ts +6 -0
  135. package/dist/data/ai/SessionViewer.tool-cost.d.ts.map +1 -0
  136. package/dist/data/ai/SessionViewer.tool-cost.js +128 -0
  137. package/dist/data/ai/SessionViewer.tool-cost.js.map +1 -0
  138. package/dist/data/ai/SessionViewer.tool-details.cjs +3 -1
  139. package/dist/data/ai/SessionViewer.tool-details.cjs.map +1 -1
  140. package/dist/data/ai/SessionViewer.tool-details.d.ts.map +1 -1
  141. package/dist/data/ai/SessionViewer.tool-details.js +3 -1
  142. package/dist/data/ai/SessionViewer.tool-details.js.map +1 -1
  143. package/dist/data/ai/SessionViewer.tool-row.cjs +55 -35
  144. package/dist/data/ai/SessionViewer.tool-row.cjs.map +1 -1
  145. package/dist/data/ai/SessionViewer.tool-row.d.ts +2 -1
  146. package/dist/data/ai/SessionViewer.tool-row.d.ts.map +1 -1
  147. package/dist/data/ai/SessionViewer.tool-row.js +55 -35
  148. package/dist/data/ai/SessionViewer.tool-row.js.map +1 -1
  149. package/dist/data/ai/SessionViewer.unified.d.ts +4 -0
  150. package/dist/data/ai/SessionViewer.unified.d.ts.map +1 -1
  151. package/dist/data/ai/SessionViewerMenu.cjs +18 -1
  152. package/dist/data/ai/SessionViewerMenu.cjs.map +1 -1
  153. package/dist/data/ai/SessionViewerMenu.d.ts +6 -1
  154. package/dist/data/ai/SessionViewerMenu.d.ts.map +1 -1
  155. package/dist/data/ai/SessionViewerMenu.js +18 -1
  156. package/dist/data/ai/SessionViewerMenu.js.map +1 -1
  157. package/dist/data/ai/ToolPreferences.cjs +149 -143
  158. package/dist/data/ai/ToolPreferences.cjs.map +1 -1
  159. package/dist/data/ai/ToolPreferences.d.ts +20 -6
  160. package/dist/data/ai/ToolPreferences.d.ts.map +1 -1
  161. package/dist/data/ai/ToolPreferences.js +151 -146
  162. package/dist/data/ai/ToolPreferences.js.map +1 -1
  163. package/dist/data/ai/ToolPreferences.model.cjs +14 -10
  164. package/dist/data/ai/ToolPreferences.model.cjs.map +1 -1
  165. package/dist/data/ai/ToolPreferences.model.d.ts +1 -0
  166. package/dist/data/ai/ToolPreferences.model.d.ts.map +1 -1
  167. package/dist/data/ai/ToolPreferences.model.js +15 -11
  168. package/dist/data/ai/ToolPreferences.model.js.map +1 -1
  169. package/dist/data/ai/ToolPreferencesList.cjs +1 -0
  170. package/dist/data/ai/ToolPreferencesList.cjs.map +1 -1
  171. package/dist/data/ai/ToolPreferencesList.d.ts +4 -1
  172. package/dist/data/ai/ToolPreferencesList.d.ts.map +1 -1
  173. package/dist/data/ai/ToolPreferencesList.js +2 -1
  174. package/dist/data/ai/ToolPreferencesList.js.map +1 -1
  175. package/dist/data/ai/ToolSchemaBrowser.cjs +52 -53
  176. package/dist/data/ai/ToolSchemaBrowser.cjs.map +1 -1
  177. package/dist/data/ai/ToolSchemaBrowser.d.ts +6 -3
  178. package/dist/data/ai/ToolSchemaBrowser.d.ts.map +1 -1
  179. package/dist/data/ai/ToolSchemaBrowser.directory-header.cjs +9 -13
  180. package/dist/data/ai/ToolSchemaBrowser.directory-header.cjs.map +1 -1
  181. package/dist/data/ai/ToolSchemaBrowser.directory-header.d.ts +5 -2
  182. package/dist/data/ai/ToolSchemaBrowser.directory-header.d.ts.map +1 -1
  183. package/dist/data/ai/ToolSchemaBrowser.directory-header.js +9 -13
  184. package/dist/data/ai/ToolSchemaBrowser.directory-header.js.map +1 -1
  185. package/dist/data/ai/ToolSchemaBrowser.js +53 -54
  186. package/dist/data/ai/ToolSchemaBrowser.js.map +1 -1
  187. package/dist/data/ai/ToolSchemaBrowser.model.cjs +19 -27
  188. package/dist/data/ai/ToolSchemaBrowser.model.cjs.map +1 -1
  189. package/dist/data/ai/ToolSchemaBrowser.model.d.ts +9 -6
  190. package/dist/data/ai/ToolSchemaBrowser.model.d.ts.map +1 -1
  191. package/dist/data/ai/ToolSchemaBrowser.model.js +20 -28
  192. package/dist/data/ai/ToolSchemaBrowser.model.js.map +1 -1
  193. package/dist/data/ai/ToolSchemaBrowser.sidebar.cjs +12 -213
  194. package/dist/data/ai/ToolSchemaBrowser.sidebar.cjs.map +1 -1
  195. package/dist/data/ai/ToolSchemaBrowser.sidebar.d.ts +1 -3
  196. package/dist/data/ai/ToolSchemaBrowser.sidebar.d.ts.map +1 -1
  197. package/dist/data/ai/ToolSchemaBrowser.sidebar.js +13 -214
  198. package/dist/data/ai/ToolSchemaBrowser.sidebar.js.map +1 -1
  199. package/dist/data/ai/ToolSchemaBrowser.strategies.cjs +54 -0
  200. package/dist/data/ai/ToolSchemaBrowser.strategies.cjs.map +1 -0
  201. package/dist/data/ai/ToolSchemaBrowser.strategies.d.ts +9 -0
  202. package/dist/data/ai/ToolSchemaBrowser.strategies.d.ts.map +1 -0
  203. package/dist/data/ai/ToolSchemaBrowser.strategies.js +54 -0
  204. package/dist/data/ai/ToolSchemaBrowser.strategies.js.map +1 -0
  205. package/dist/data/ai/ToolSchemaBrowser.tree.cjs +179 -0
  206. package/dist/data/ai/ToolSchemaBrowser.tree.cjs.map +1 -0
  207. package/dist/data/ai/ToolSchemaBrowser.tree.d.ts +20 -0
  208. package/dist/data/ai/ToolSchemaBrowser.tree.d.ts.map +1 -0
  209. package/dist/data/ai/ToolSchemaBrowser.tree.js +179 -0
  210. package/dist/data/ai/ToolSchemaBrowser.tree.js.map +1 -0
  211. package/dist/data/ai/index.d.ts +2 -2
  212. package/dist/data/ai/index.d.ts.map +1 -1
  213. package/dist/data/ai/runtime-profiles/PermissionStrategiesEditor.cjs +8 -28
  214. package/dist/data/ai/runtime-profiles/PermissionStrategiesEditor.cjs.map +1 -1
  215. package/dist/data/ai/runtime-profiles/PermissionStrategiesEditor.d.ts.map +1 -1
  216. package/dist/data/ai/runtime-profiles/PermissionStrategiesEditor.js +9 -29
  217. package/dist/data/ai/runtime-profiles/PermissionStrategiesEditor.js.map +1 -1
  218. package/dist/data/ai/session-token-sizing.d.ts +32 -0
  219. package/dist/data/ai/session-token-sizing.d.ts.map +1 -0
  220. package/dist/data/ai/use-session-token-sizing.cjs +73 -0
  221. package/dist/data/ai/use-session-token-sizing.cjs.map +1 -0
  222. package/dist/data/ai/use-session-token-sizing.d.ts +21 -0
  223. package/dist/data/ai/use-session-token-sizing.d.ts.map +1 -0
  224. package/dist/data/ai/use-session-token-sizing.js +73 -0
  225. package/dist/data/ai/use-session-token-sizing.js.map +1 -0
  226. package/dist/data/call-graph/CallGraph.cjs +269 -0
  227. package/dist/data/call-graph/CallGraph.cjs.map +1 -0
  228. package/dist/data/call-graph/CallGraph.d.ts +78 -0
  229. package/dist/data/call-graph/CallGraph.d.ts.map +1 -0
  230. package/dist/data/call-graph/CallGraph.js +269 -0
  231. package/dist/data/call-graph/CallGraph.js.map +1 -0
  232. package/dist/data/call-graph/CallGraphGlyphs.cjs +39 -0
  233. package/dist/data/call-graph/CallGraphGlyphs.cjs.map +1 -0
  234. package/dist/data/call-graph/CallGraphGlyphs.d.ts +19 -0
  235. package/dist/data/call-graph/CallGraphGlyphs.d.ts.map +1 -0
  236. package/dist/data/call-graph/CallGraphGlyphs.js +39 -0
  237. package/dist/data/call-graph/CallGraphGlyphs.js.map +1 -0
  238. package/dist/data/call-graph/CallGraphMembers.cjs +51 -0
  239. package/dist/data/call-graph/CallGraphMembers.cjs.map +1 -0
  240. package/dist/data/call-graph/CallGraphMembers.d.ts +22 -0
  241. package/dist/data/call-graph/CallGraphMembers.d.ts.map +1 -0
  242. package/dist/data/call-graph/CallGraphMembers.js +51 -0
  243. package/dist/data/call-graph/CallGraphMembers.js.map +1 -0
  244. package/dist/data/call-graph/CallGraphParts.cjs +204 -0
  245. package/dist/data/call-graph/CallGraphParts.cjs.map +1 -0
  246. package/dist/data/call-graph/CallGraphParts.d.ts +44 -0
  247. package/dist/data/call-graph/CallGraphParts.d.ts.map +1 -0
  248. package/dist/data/call-graph/CallGraphParts.js +204 -0
  249. package/dist/data/call-graph/CallGraphParts.js.map +1 -0
  250. package/dist/data/call-graph/CallGraphToolbar.cjs +198 -0
  251. package/dist/data/call-graph/CallGraphToolbar.cjs.map +1 -0
  252. package/dist/data/call-graph/CallGraphToolbar.d.ts +55 -0
  253. package/dist/data/call-graph/CallGraphToolbar.d.ts.map +1 -0
  254. package/dist/data/call-graph/CallGraphToolbar.js +198 -0
  255. package/dist/data/call-graph/CallGraphToolbar.js.map +1 -0
  256. package/dist/data/call-graph/call-graph-exclude.cjs +75 -0
  257. package/dist/data/call-graph/call-graph-exclude.cjs.map +1 -0
  258. package/dist/data/call-graph/call-graph-exclude.d.ts +31 -0
  259. package/dist/data/call-graph/call-graph-exclude.d.ts.map +1 -0
  260. package/dist/data/call-graph/call-graph-exclude.js +75 -0
  261. package/dist/data/call-graph/call-graph-exclude.js.map +1 -0
  262. package/dist/data/call-graph/call-graph-labels.cjs +96 -0
  263. package/dist/data/call-graph/call-graph-labels.cjs.map +1 -0
  264. package/dist/data/call-graph/call-graph-labels.d.ts +53 -0
  265. package/dist/data/call-graph/call-graph-labels.d.ts.map +1 -0
  266. package/dist/data/call-graph/call-graph-labels.js +96 -0
  267. package/dist/data/call-graph/call-graph-labels.js.map +1 -0
  268. package/dist/data/call-graph/call-graph-model.cjs +312 -0
  269. package/dist/data/call-graph/call-graph-model.cjs.map +1 -0
  270. package/dist/data/call-graph/call-graph-model.d.ts +138 -0
  271. package/dist/data/call-graph/call-graph-model.d.ts.map +1 -0
  272. package/dist/data/call-graph/call-graph-model.js +312 -0
  273. package/dist/data/call-graph/call-graph-model.js.map +1 -0
  274. package/dist/data/call-graph/call-graph-vocabulary.cjs +195 -0
  275. package/dist/data/call-graph/call-graph-vocabulary.cjs.map +1 -0
  276. package/dist/data/call-graph/call-graph-vocabulary.d.ts +76 -0
  277. package/dist/data/call-graph/call-graph-vocabulary.d.ts.map +1 -0
  278. package/dist/data/call-graph/call-graph-vocabulary.js +195 -0
  279. package/dist/data/call-graph/call-graph-vocabulary.js.map +1 -0
  280. package/dist/data/call-graph/call-graph.fixtures.d.ts +63 -0
  281. package/dist/data/call-graph/call-graph.fixtures.d.ts.map +1 -0
  282. package/dist/data/call-graph/index.d.ts +7 -0
  283. package/dist/data/call-graph/index.d.ts.map +1 -0
  284. package/dist/data/call-graph/types.cjs +5 -0
  285. package/dist/data/call-graph/types.cjs.map +1 -0
  286. package/dist/data/call-graph/types.d.ts +140 -0
  287. package/dist/data/call-graph/types.d.ts.map +1 -0
  288. package/dist/data/call-graph/types.js +5 -0
  289. package/dist/data/call-graph/types.js.map +1 -0
  290. package/dist/data/call-graph/use-call-graph.cjs +93 -0
  291. package/dist/data/call-graph/use-call-graph.cjs.map +1 -0
  292. package/dist/data/call-graph/use-call-graph.d.ts +24 -0
  293. package/dist/data/call-graph/use-call-graph.d.ts.map +1 -0
  294. package/dist/data/call-graph/use-call-graph.js +93 -0
  295. package/dist/data/call-graph/use-call-graph.js.map +1 -0
  296. package/dist/data/chat/Chat.cjs +39 -15
  297. package/dist/data/chat/Chat.cjs.map +1 -1
  298. package/dist/data/chat/Chat.d.ts.map +1 -1
  299. package/dist/data/chat/Chat.fixtures.cjs +2 -2
  300. package/dist/data/chat/Chat.fixtures.cjs.map +1 -1
  301. package/dist/data/chat/Chat.fixtures.js +2 -2
  302. package/dist/data/chat/Chat.fixtures.js.map +1 -1
  303. package/dist/data/chat/Chat.js +40 -16
  304. package/dist/data/chat/Chat.js.map +1 -1
  305. package/dist/data/chat/ChatRuntimeToolbar.cjs +3 -6
  306. package/dist/data/chat/ChatRuntimeToolbar.cjs.map +1 -1
  307. package/dist/data/chat/ChatRuntimeToolbar.d.ts.map +1 -1
  308. package/dist/data/chat/ChatRuntimeToolbar.js +3 -6
  309. package/dist/data/chat/ChatRuntimeToolbar.js.map +1 -1
  310. package/dist/data/chat/ContextMeter.bar.cjs +5 -8
  311. package/dist/data/chat/ContextMeter.bar.cjs.map +1 -1
  312. package/dist/data/chat/ContextMeter.bar.d.ts +1 -1
  313. package/dist/data/chat/ContextMeter.bar.d.ts.map +1 -1
  314. package/dist/data/chat/ContextMeter.bar.js +5 -8
  315. package/dist/data/chat/ContextMeter.bar.js.map +1 -1
  316. package/dist/data/chat/ContextMeter.cjs +18 -19
  317. package/dist/data/chat/ContextMeter.cjs.map +1 -1
  318. package/dist/data/chat/ContextMeter.d.ts +1 -1
  319. package/dist/data/chat/ContextMeter.d.ts.map +1 -1
  320. package/dist/data/chat/ContextMeter.js +18 -19
  321. package/dist/data/chat/ContextMeter.js.map +1 -1
  322. package/dist/data/chat/Conversation.cjs +2 -1
  323. package/dist/data/chat/Conversation.cjs.map +1 -1
  324. package/dist/data/chat/Conversation.d.ts +4 -1
  325. package/dist/data/chat/Conversation.d.ts.map +1 -1
  326. package/dist/data/chat/Conversation.js +2 -1
  327. package/dist/data/chat/Conversation.js.map +1 -1
  328. package/dist/data/chat/Message.cjs +39 -12
  329. package/dist/data/chat/Message.cjs.map +1 -1
  330. package/dist/data/chat/Message.d.ts +1 -1
  331. package/dist/data/chat/Message.d.ts.map +1 -1
  332. package/dist/data/chat/Message.js +40 -13
  333. package/dist/data/chat/Message.js.map +1 -1
  334. package/dist/data/chat/ToolCall.cjs +60 -5
  335. package/dist/data/chat/ToolCall.cjs.map +1 -1
  336. package/dist/data/chat/ToolCall.d.ts +7 -2
  337. package/dist/data/chat/ToolCall.d.ts.map +1 -1
  338. package/dist/data/chat/ToolCall.js +60 -5
  339. package/dist/data/chat/ToolCall.js.map +1 -1
  340. package/dist/data/chat/approval.cjs.map +1 -1
  341. package/dist/data/chat/approval.d.ts +2 -2
  342. package/dist/data/chat/approval.d.ts.map +1 -1
  343. package/dist/data/chat/approval.js.map +1 -1
  344. package/dist/data/chat/tool-policy.cjs +59 -2
  345. package/dist/data/chat/tool-policy.cjs.map +1 -1
  346. package/dist/data/chat/tool-policy.d.ts +9 -0
  347. package/dist/data/chat/tool-policy.d.ts.map +1 -1
  348. package/dist/data/chat/tool-policy.js +59 -2
  349. package/dist/data/chat/tool-policy.js.map +1 -1
  350. package/dist/data/chat/types.cjs +6 -0
  351. package/dist/data/chat/types.cjs.map +1 -1
  352. package/dist/data/chat/types.d.ts +13 -4
  353. package/dist/data/chat/types.d.ts.map +1 -1
  354. package/dist/data/chat/types.js +7 -1
  355. package/dist/data/chat/types.js.map +1 -1
  356. package/dist/data/chat/usage-snapshot.cjs +11 -6
  357. package/dist/data/chat/usage-snapshot.cjs.map +1 -1
  358. package/dist/data/chat/usage-snapshot.d.ts +0 -1
  359. package/dist/data/chat/usage-snapshot.d.ts.map +1 -1
  360. package/dist/data/chat/usage-snapshot.js +11 -6
  361. package/dist/data/chat/usage-snapshot.js.map +1 -1
  362. package/dist/data/data-access.cjs +8 -0
  363. package/dist/data/data-access.cjs.map +1 -0
  364. package/dist/data/data-access.d.ts +5 -0
  365. package/dist/data/data-access.d.ts.map +1 -0
  366. package/dist/data/data-access.js +8 -0
  367. package/dist/data/data-access.js.map +1 -0
  368. package/dist/data/diagnostics/StackFrameRow.cjs +3 -3
  369. package/dist/data/diagnostics/StackFrameRow.cjs.map +1 -1
  370. package/dist/data/diagnostics/StackFrameRow.js +3 -3
  371. package/dist/data/diagnostics/StackFrameRow.js.map +1 -1
  372. package/dist/data/git/GitChangeList.cjs +6 -2
  373. package/dist/data/git/GitChangeList.cjs.map +1 -1
  374. package/dist/data/git/GitChangeList.d.ts +6 -1
  375. package/dist/data/git/GitChangeList.d.ts.map +1 -1
  376. package/dist/data/git/GitChangeList.js +6 -2
  377. package/dist/data/git/GitChangeList.js.map +1 -1
  378. package/dist/data/graph-columns-layout.cjs +61 -14
  379. package/dist/data/graph-columns-layout.cjs.map +1 -1
  380. package/dist/data/graph-columns-layout.d.ts +42 -0
  381. package/dist/data/graph-columns-layout.d.ts.map +1 -1
  382. package/dist/data/graph-columns-layout.js +61 -14
  383. package/dist/data/graph-columns-layout.js.map +1 -1
  384. package/dist/data/graph-diagram-model.cjs +5 -0
  385. package/dist/data/graph-diagram-model.cjs.map +1 -1
  386. package/dist/data/graph-diagram-model.d.ts +24 -0
  387. package/dist/data/graph-diagram-model.d.ts.map +1 -1
  388. package/dist/data/graph-diagram-model.js +5 -0
  389. package/dist/data/graph-diagram-model.js.map +1 -1
  390. package/dist/data/graph-edge-routing.cjs +9 -3
  391. package/dist/data/graph-edge-routing.cjs.map +1 -1
  392. package/dist/data/graph-edge-routing.d.ts +2 -0
  393. package/dist/data/graph-edge-routing.d.ts.map +1 -1
  394. package/dist/data/graph-edge-routing.js +9 -3
  395. package/dist/data/graph-edge-routing.js.map +1 -1
  396. package/dist/data/graph-group-window.cjs +60 -0
  397. package/dist/data/graph-group-window.cjs.map +1 -0
  398. package/dist/data/graph-group-window.d.ts +33 -0
  399. package/dist/data/graph-group-window.d.ts.map +1 -0
  400. package/dist/data/graph-group-window.js +60 -0
  401. package/dist/data/graph-group-window.js.map +1 -0
  402. package/dist/data/json-view/JsonSource.cjs +84 -0
  403. package/dist/data/json-view/JsonSource.cjs.map +1 -0
  404. package/dist/data/json-view/JsonSource.d.ts +7 -0
  405. package/dist/data/json-view/JsonSource.d.ts.map +1 -0
  406. package/dist/data/json-view/JsonSource.js +84 -0
  407. package/dist/data/json-view/JsonSource.js.map +1 -0
  408. package/dist/data/json-view/parse-prefix.cjs +132 -0
  409. package/dist/data/json-view/parse-prefix.cjs.map +1 -0
  410. package/dist/data/json-view/parse-prefix.d.ts +11 -0
  411. package/dist/data/json-view/parse-prefix.d.ts.map +1 -0
  412. package/dist/data/json-view/parse-prefix.js +132 -0
  413. package/dist/data/json-view/parse-prefix.js.map +1 -0
  414. package/dist/data/json-view/parse-source.cjs +62 -0
  415. package/dist/data/json-view/parse-source.cjs.map +1 -0
  416. package/dist/data/json-view/parse-source.d.ts +16 -0
  417. package/dist/data/json-view/parse-source.d.ts.map +1 -0
  418. package/dist/data/json-view/parse-source.js +62 -0
  419. package/dist/data/json-view/parse-source.js.map +1 -0
  420. package/dist/data/json-view/story-fixtures.d.ts +6 -0
  421. package/dist/data/json-view/story-fixtures.d.ts.map +1 -0
  422. package/dist/data/json-view/types.d.ts +14 -0
  423. package/dist/data/json-view/types.d.ts.map +1 -0
  424. package/dist/data/runtime/RuntimeBar.cjs +2 -5
  425. package/dist/data/runtime/RuntimeBar.cjs.map +1 -1
  426. package/dist/data/runtime/RuntimeBar.d.ts +2 -4
  427. package/dist/data/runtime/RuntimeBar.d.ts.map +1 -1
  428. package/dist/data/runtime/RuntimeBar.fields.cjs +2 -2
  429. package/dist/data/runtime/RuntimeBar.fields.cjs.map +1 -1
  430. package/dist/data/runtime/RuntimeBar.fields.js +2 -2
  431. package/dist/data/runtime/RuntimeBar.fields.js.map +1 -1
  432. package/dist/data/runtime/RuntimeBar.js +2 -5
  433. package/dist/data/runtime/RuntimeBar.js.map +1 -1
  434. package/dist/data/runtime/RuntimeBar.selection.cjs +4 -1
  435. package/dist/data/runtime/RuntimeBar.selection.cjs.map +1 -1
  436. package/dist/data/runtime/RuntimeBar.selection.d.ts.map +1 -1
  437. package/dist/data/runtime/RuntimeBar.selection.js +5 -2
  438. package/dist/data/runtime/RuntimeBar.selection.js.map +1 -1
  439. package/dist/data/runtime/RuntimeBarActions.cjs +1 -5
  440. package/dist/data/runtime/RuntimeBarActions.cjs.map +1 -1
  441. package/dist/data/runtime/RuntimeBarActions.d.ts +1 -1
  442. package/dist/data/runtime/RuntimeBarActions.d.ts.map +1 -1
  443. package/dist/data/runtime/RuntimeBarActions.js +1 -5
  444. package/dist/data/runtime/RuntimeBarActions.js.map +1 -1
  445. package/dist/data/runtime/RuntimeBarIdentity.cjs +6 -14
  446. package/dist/data/runtime/RuntimeBarIdentity.cjs.map +1 -1
  447. package/dist/data/runtime/RuntimeBarIdentity.d.ts +0 -1
  448. package/dist/data/runtime/RuntimeBarIdentity.d.ts.map +1 -1
  449. package/dist/data/runtime/RuntimeBarIdentity.js +6 -14
  450. package/dist/data/runtime/RuntimeBarIdentity.js.map +1 -1
  451. package/dist/data/runtime/RuntimeBarLayout.cjs +8 -27
  452. package/dist/data/runtime/RuntimeBarLayout.cjs.map +1 -1
  453. package/dist/data/runtime/RuntimeBarLayout.d.ts.map +1 -1
  454. package/dist/data/runtime/RuntimeBarLayout.js +8 -27
  455. package/dist/data/runtime/RuntimeBarLayout.js.map +1 -1
  456. package/dist/data/runtime/RuntimeBarSegment.cjs +1 -5
  457. package/dist/data/runtime/RuntimeBarSegment.cjs.map +1 -1
  458. package/dist/data/runtime/RuntimeBarSegment.d.ts.map +1 -1
  459. package/dist/data/runtime/RuntimeBarSegment.js +1 -5
  460. package/dist/data/runtime/RuntimeBarSegment.js.map +1 -1
  461. package/dist/data/runtime/use-runtime-bar-overflow.cjs +4 -10
  462. package/dist/data/runtime/use-runtime-bar-overflow.cjs.map +1 -1
  463. package/dist/data/runtime/use-runtime-bar-overflow.d.ts +1 -2
  464. package/dist/data/runtime/use-runtime-bar-overflow.d.ts.map +1 -1
  465. package/dist/data/runtime/use-runtime-bar-overflow.js +4 -10
  466. package/dist/data/runtime/use-runtime-bar-overflow.js.map +1 -1
  467. package/dist/data/test-runner/TestRunner.fixtures.d.ts +0 -20
  468. package/dist/data/test-runner/TestRunner.fixtures.d.ts.map +1 -1
  469. package/dist/data/test-runner/TestRunner.large-fixtures.d.ts +22 -0
  470. package/dist/data/test-runner/TestRunner.large-fixtures.d.ts.map +1 -0
  471. package/dist/data/use-group-windows.cjs +50 -0
  472. package/dist/data/use-group-windows.cjs.map +1 -0
  473. package/dist/data/use-group-windows.d.ts +27 -0
  474. package/dist/data/use-group-windows.d.ts.map +1 -0
  475. package/dist/data/use-group-windows.js +50 -0
  476. package/dist/data/use-group-windows.js.map +1 -0
  477. package/dist/data/use-pan-zoom.cjs +23 -10
  478. package/dist/data/use-pan-zoom.cjs.map +1 -1
  479. package/dist/data/use-pan-zoom.d.ts +16 -2
  480. package/dist/data/use-pan-zoom.d.ts.map +1 -1
  481. package/dist/data/use-pan-zoom.js +23 -10
  482. package/dist/data/use-pan-zoom.js.map +1 -1
  483. package/dist/data/version-info.cjs +3 -3
  484. package/dist/data/version-info.js +3 -3
  485. package/dist/data.cjs +36 -2
  486. package/dist/data.cjs.map +1 -1
  487. package/dist/data.d.ts +5 -2
  488. package/dist/data.d.ts.map +1 -1
  489. package/dist/data.js +35 -1
  490. package/dist/data.js.map +1 -1
  491. package/dist/hooks/event-hub.cjs +229 -0
  492. package/dist/hooks/event-hub.cjs.map +1 -0
  493. package/dist/hooks/event-hub.d.ts +26 -0
  494. package/dist/hooks/event-hub.d.ts.map +1 -0
  495. package/dist/hooks/event-hub.js +229 -0
  496. package/dist/hooks/event-hub.js.map +1 -0
  497. package/dist/hooks.cjs +2 -0
  498. package/dist/hooks.cjs.map +1 -1
  499. package/dist/hooks.d.ts +1 -0
  500. package/dist/hooks.d.ts.map +1 -1
  501. package/dist/hooks.js +2 -0
  502. package/dist/hooks.js.map +1 -1
  503. package/dist/index.cjs +40 -4
  504. package/dist/index.cjs.map +1 -1
  505. package/dist/index.js +37 -1
  506. package/dist/index.js.map +1 -1
  507. package/dist/layout/Workspace.cjs +13 -4
  508. package/dist/layout/Workspace.cjs.map +1 -1
  509. package/dist/layout/Workspace.d.ts +7 -2
  510. package/dist/layout/Workspace.d.ts.map +1 -1
  511. package/dist/layout/Workspace.js +13 -4
  512. package/dist/layout/Workspace.js.map +1 -1
  513. package/dist/lib/permission-strategies.cjs +71 -11
  514. package/dist/lib/permission-strategies.cjs.map +1 -1
  515. package/dist/lib/permission-strategies.d.ts +3 -0
  516. package/dist/lib/permission-strategies.d.ts.map +1 -1
  517. package/dist/lib/permission-strategies.js +71 -11
  518. package/dist/lib/permission-strategies.js.map +1 -1
  519. package/dist/overlay/modalStack.cjs +13 -6
  520. package/dist/overlay/modalStack.cjs.map +1 -1
  521. package/dist/overlay/modalStack.d.ts.map +1 -1
  522. package/dist/overlay/modalStack.js +13 -6
  523. package/dist/overlay/modalStack.js.map +1 -1
  524. package/dist/styles.css +1 -1
  525. package/package.json +5 -3
  526. package/dist/data/ai/ToolSchemaBrowser.selection-toolbar.cjs +0 -57
  527. package/dist/data/ai/ToolSchemaBrowser.selection-toolbar.cjs.map +0 -1
  528. package/dist/data/ai/ToolSchemaBrowser.selection-toolbar.d.ts +0 -7
  529. package/dist/data/ai/ToolSchemaBrowser.selection-toolbar.d.ts.map +0 -1
  530. package/dist/data/ai/ToolSchemaBrowser.selection-toolbar.js +0 -57
  531. package/dist/data/ai/ToolSchemaBrowser.selection-toolbar.js.map +0 -1
  532. package/dist/data/runtime/RuntimeBar.context.cjs +0 -8
  533. package/dist/data/runtime/RuntimeBar.context.cjs.map +0 -1
  534. package/dist/data/runtime/RuntimeBar.context.d.ts +0 -2
  535. package/dist/data/runtime/RuntimeBar.context.d.ts.map +0 -1
  536. package/dist/data/runtime/RuntimeBar.context.js +0 -8
  537. package/dist/data/runtime/RuntimeBar.context.js.map +0 -1
@@ -5,7 +5,9 @@ import { IconButton } from "../components/IconButton.js";
5
5
  import { columnsLayout } from "./graph-columns-layout.js";
6
6
  import { ringLayout } from "./graph-layout.js";
7
7
  import { GraphDiagramEdgePaths, GraphDiagramEdgeLabels } from "./GraphDiagramEdges.js";
8
- import { GraphDiagramGroupBoxes, GraphDiagramNodes } from "./GraphDiagramNodes.js";
8
+ import { GraphDiagramGroupBoxes } from "./GraphDiagramGroups.js";
9
+ import { GraphDiagramNodes } from "./GraphDiagramNodes.js";
10
+ import { useGroupWindows } from "./use-group-windows.js";
9
11
  import { requireEntry } from "./graph-diagram-model.js";
10
12
  import { useEdgeFocus } from "./use-edge-focus.js";
11
13
  import { usePanZoom } from "./use-pan-zoom.js";
@@ -16,6 +18,25 @@ import { UiFullscreen } from "../icons/components/UiFullscreen.js";
16
18
  import { UiHome } from "../icons/components/UiHome.js";
17
19
  const DEFAULT_NODE_WIDTH = 168;
18
20
  const DEFAULT_NODE_HEIGHT = 60;
21
+ const DEFAULT_COMPACT_NODE_HEIGHT = 24;
22
+ function compactHeights(nodes, layout, compactNodeHeight, standIns, headerHeight) {
23
+ if (layout !== "columns") return {};
24
+ return Object.fromEntries(nodes.flatMap((node) => {
25
+ if (standIns.has(node.id)) return [[node.id, headerHeight]];
26
+ return node.size === "compact" ? [[node.id, compactNodeHeight]] : [];
27
+ }));
28
+ }
29
+ function collapsedStandIns(nodes, groups) {
30
+ const collapsed = new Set(groups == null ? void 0 : groups.filter((group) => group.collapsed === true).map((group) => group.id));
31
+ const standIns = /* @__PURE__ */ new Map();
32
+ for (const node of nodes) {
33
+ if (node.group === void 0 || !collapsed.has(node.group)) continue;
34
+ const held = standIns.get(node.group);
35
+ if (held !== void 0) throw new Error(`GraphDiagram: collapsed group "${node.group}" holds "${held}" and "${node.id}"; it draws one stand-in`);
36
+ standIns.set(node.group, node.id);
37
+ }
38
+ return standIns;
39
+ }
19
40
  function assertEdgesReferenceKnownNodes(nodes, edges) {
20
41
  const ids = new Set(nodes.map((node) => node.id));
21
42
  for (const edge of edges) {
@@ -33,7 +54,7 @@ function requireLevel(node) {
33
54
  }
34
55
  return node.level;
35
56
  }
36
- function layoutNodes(nodes, edges, { layout, nodeWidth, nodeHeight, columnGap, rowGap }) {
57
+ function layoutNodes(nodes, edges, { layout, nodeWidth, nodeHeight, compactNodeHeight, records, collapsed, recordHeaderHeight, columnGap, rowGap }) {
37
58
  switch (layout) {
38
59
  case "ring":
39
60
  return { ...ringLayout(nodes, { nodeWidth, nodeHeight }), groups: [] };
@@ -42,12 +63,17 @@ function layoutNodes(nodes, edges, { layout, nodeWidth, nodeHeight, columnGap, r
42
63
  nodes.map((node) => ({
43
64
  id: node.id,
44
65
  level: requireLevel(node),
45
- ...node.group !== void 0 ? { group: node.group } : {}
66
+ ...node.group !== void 0 ? { group: node.group } : {},
67
+ ...node.size === "compact" ? { compact: true } : {}
46
68
  })),
47
69
  edges,
48
70
  {
49
71
  nodeWidth,
50
72
  nodeHeight,
73
+ compactNodeHeight,
74
+ records,
75
+ collapsed,
76
+ recordHeaderHeight,
51
77
  ...columnGap !== void 0 ? { columnGap } : {},
52
78
  ...rowGap !== void 0 ? { rowGap } : {}
53
79
  }
@@ -90,11 +116,15 @@ function GraphDiagram({
90
116
  onEdgeSelect,
91
117
  edgeFocus = "auto",
92
118
  groups,
119
+ onGroupToggle,
93
120
  nodeWidth = DEFAULT_NODE_WIDTH,
94
121
  nodeHeight = DEFAULT_NODE_HEIGHT,
122
+ compactNodeHeight = DEFAULT_COMPACT_NODE_HEIGHT,
123
+ recordHeaderHeight = 24,
95
124
  columnGap,
96
125
  rowGap,
97
126
  zoomable = false,
127
+ wheelZoom = "modifier",
98
128
  fitMinScale,
99
129
  focusId,
100
130
  maxHeight,
@@ -103,20 +133,39 @@ function GraphDiagram({
103
133
  }) {
104
134
  assertEdgesReferenceKnownNodes(nodes, edges);
105
135
  const markerPrefix = `graph-diagram-${useId().replace(/[^a-zA-Z0-9_-]/g, "")}`;
106
- const { width, height, positions, groups: groupBoxes } = useMemo(
107
- () => layoutNodes(nodes, edges, { layout, nodeWidth, nodeHeight, columnGap, rowGap }),
108
- [layout, nodes, edges, nodeWidth, nodeHeight, columnGap, rowGap]
136
+ const records = useMemo(() => (groups == null ? void 0 : groups.filter((group) => group.variant === "record").map((group) => group.id)) ?? [], [groups]);
137
+ const recordNodes = useMemo(() => new Set(layout === "columns" ? nodes.filter((node) => node.group !== void 0 && records.includes(node.group)).map((node) => node.id) : []), [layout, nodes, records]);
138
+ const standIns = useMemo(() => layout === "columns" ? collapsedStandIns(nodes, groups) : /* @__PURE__ */ new Map(), [layout, nodes, groups]);
139
+ const collapsed = useMemo(() => [...standIns.keys()], [standIns]);
140
+ const { width, height, positions: laidOut, groups: groupBoxes } = useMemo(
141
+ () => layoutNodes(nodes, edges, { layout, nodeWidth, nodeHeight, compactNodeHeight, records, collapsed, recordHeaderHeight, columnGap, rowGap }),
142
+ [layout, nodes, edges, nodeWidth, nodeHeight, compactNodeHeight, records, collapsed, recordHeaderHeight, columnGap, rowGap]
109
143
  );
110
- const routes = useMemo(
111
- () => routeEdges(edges, positions, { nodeWidth, nodeHeight }, { anchor: layout === "columns" ? "side" : "center" }),
112
- [edges, positions, nodeWidth, nodeHeight, layout]
144
+ const nodeHeights = useMemo(
145
+ () => compactHeights(nodes, layout, compactNodeHeight, new Set(standIns.values()), recordHeaderHeight),
146
+ [nodes, layout, compactNodeHeight, standIns, recordHeaderHeight]
113
147
  );
114
148
  const panZoom = usePanZoom({
115
149
  enabled: zoomable,
150
+ wheel: wheelZoom,
116
151
  contentWidth: width,
117
152
  contentHeight: height,
118
- opening: openingFit(positions, fitMinScale, focusId)
153
+ opening: openingFit(laidOut, fitMinScale, focusId)
119
154
  });
155
+ const windows = useGroupWindows({ boxes: groupBoxes, positions: laidOut, reveal: selectedId ?? focusId, stageRef: panZoom.contentRef, scale: zoomable ? panZoom.transform.scale : 1 });
156
+ const { positions } = windows;
157
+ const routes = useMemo(
158
+ () => routeEdges(edges, positions, { nodeWidth, nodeHeight, nodeHeights }, { anchor: layout === "columns" ? "side" : "center" }),
159
+ [edges, positions, nodeWidth, nodeHeight, nodeHeights, layout]
160
+ );
161
+ const drawnNodes = useMemo(() => {
162
+ const standing = new Set(standIns.values());
163
+ return nodes.filter((node) => !windows.hidden.has(node.id) && !standing.has(node.id));
164
+ }, [nodes, windows.hidden, standIns]);
165
+ const windowOf = useMemo(
166
+ () => new Map(groupBoxes.flatMap((box) => box.window ? box.window.members.map((id) => [id, box.id]) : [])),
167
+ [groupBoxes]
168
+ );
120
169
  const natural = layout === "columns" || zoomable;
121
170
  const place = natural ? ({ x, y }) => ({ left: x, top: y }) : ({ x, y }) => ({ left: toPercent(x, width), top: toPercent(y, height) });
122
171
  const focus = useEdgeFocus({ mode: edgeFocus, edges, selectedId, selectedEdgeId });
@@ -142,7 +191,19 @@ function GraphDiagram({
142
191
  className: cn("relative", natural ? !zoomable && "mx-auto" : "w-full"),
143
192
  style: stageStyle({ width, height }, natural, zoomable ? panZoom : void 0),
144
193
  children: [
145
- /* @__PURE__ */ jsx(GraphDiagramGroupBoxes, { boxes: groupBoxes, groups }),
194
+ /* @__PURE__ */ jsx(
195
+ GraphDiagramGroupBoxes,
196
+ {
197
+ boxes: groupBoxes,
198
+ groups,
199
+ starts: windows.starts,
200
+ onScroll: windows.scroll,
201
+ onGroupToggle,
202
+ standIns,
203
+ selectedId,
204
+ onNodeSelect
205
+ }
206
+ ),
146
207
  /* @__PURE__ */ jsx(
147
208
  GraphDiagramEdgePaths,
148
209
  {
@@ -162,11 +223,14 @@ function GraphDiagram({
162
223
  /* @__PURE__ */ jsx(
163
224
  GraphDiagramNodes,
164
225
  {
165
- nodes,
226
+ nodes: drawnNodes,
166
227
  positions,
228
+ windowOf,
167
229
  place,
168
230
  nodeWidth,
169
231
  nodeHeight,
232
+ nodeHeights,
233
+ recordNodes,
170
234
  selectedId,
171
235
  onNodeSelect,
172
236
  onNodeExpand,
@@ -1 +1 @@
1
- {"version":3,"file":"GraphDiagram.js","sources":["../../src/data/GraphDiagram.tsx"],"sourcesContent":["import { useId, useMemo, type CSSProperties } from \"react\";\nimport { cn } from \"../lib/utils\";\nimport { IconButton } from \"../components/IconButton\";\nimport { UiFullscreen, UiHome, UiZoomIn, UiZoomOut } from \"../icons\";\nimport { columnsLayout, type ColumnsLayoutResult } from \"./graph-columns-layout\";\nimport { ringLayout, routeEdges, type GraphLayoutPosition } from \"./graph-layout\";\nimport { GraphDiagramEdgeLabels, GraphDiagramEdgePaths } from \"./GraphDiagramEdges\";\nimport { GraphDiagramGroupBoxes, GraphDiagramNodes } from \"./GraphDiagramNodes\";\nimport {\n requireEntry,\n type GraphDiagramEdge,\n type GraphDiagramEdgeFocus,\n type GraphDiagramGroup,\n type GraphDiagramLayout,\n type GraphDiagramNode,\n type GraphPlacer,\n} from \"./graph-diagram-model\";\nimport { useEdgeFocus } from \"./use-edge-focus\";\nimport { usePanZoom, type FitOptions, type PanZoom } from \"./use-pan-zoom\";\n\nexport type {\n GraphDiagramEdge,\n GraphDiagramEdgeFocus,\n GraphDiagramGroup,\n GraphDiagramLayout,\n GraphDiagramNode,\n} from \"./graph-diagram-model\";\n\n// GraphDiagram renders a generic, type-agnostic node/edge diagram. It knows\n// nothing about the domain: a producer maps its data into\n// GraphDiagramNode/GraphDiagramEdge and gets layout, edge routing and\n// selection behaviour.\n//\n// \"ring\" suits a small cycle of resources and processes — relationships with\n// back edges or reciprocal pairs. \"columns\" suits a directed graph with a\n// natural depth (a call graph, a dependency chain): nodes sit in the column of\n// their `level`, grouped and boxed by `group`.\n//\n// The \"columns\" layout, and any zoomable diagram, is drawn at its natural\n// pixel size so node boxes, edges and group boxes share one coordinate system\n// at every container width and zoom level. A non-zoomable \"ring\" keeps scaling\n// its node positions to the container width.\n\nexport interface GraphDiagramProps {\n nodes: GraphDiagramNode[];\n edges: GraphDiagramEdge[];\n /** Defaults to \"ring\". \"columns\" needs a `level` on every node. */\n layout?: GraphDiagramLayout;\n selectedId?: string;\n onNodeSelect?: (id: string) => void;\n /** Called by a node's `+N` control (see `expandCount`); does not select the node. */\n onNodeExpand?: (id: string) => void;\n selectedEdgeId?: string;\n /** Makes edges, and their label pills, selectable. */\n onEdgeSelect?: (id: string) => void;\n /**\n * Whether an edge shows its pill only while in focus, and fades while another is. Defaults to\n * \"auto\": a diagram with more than 32 edges is focused, a smaller one shows everything.\n */\n edgeFocus?: GraphDiagramEdgeFocus;\n /** \"columns\" layout: captions for the group rectangles. A group without an entry shows its id. */\n groups?: GraphDiagramGroup[];\n nodeWidth?: number;\n nodeHeight?: number;\n /** \"columns\" layout: horizontal gap between columns in px. Leave room for edge label pills. */\n columnGap?: number;\n /** \"columns\" layout: vertical gap between stacked nodes in px. */\n rowGap?: number;\n /** Ctrl/meta + wheel (or pinch) zooms, dragging the background pans, and zoom controls appear. */\n zoomable?: boolean;\n /**\n * Zoomable: the smallest scale the diagram opens at, so its text stays readable. A diagram too\n * large for it opens overflowing, centred on `focusId`, and is panned to reach the rest. `Fit to\n * view` still shows everything, and `Reset view` returns here. Unset, the diagram opens whole.\n */\n fitMinScale?: number;\n /** Zoomable: the node an overflowing diagram opens centred on. Defaults to the diagram's centre. */\n focusId?: string;\n maxHeight?: number | string;\n ariaLabel: string;\n className?: string;\n}\n\nconst DEFAULT_NODE_WIDTH = 168;\nconst DEFAULT_NODE_HEIGHT = 60;\n\ninterface LayoutOptions {\n layout: GraphDiagramLayout;\n nodeWidth: number;\n nodeHeight: number;\n columnGap: number | undefined;\n rowGap: number | undefined;\n}\n\nfunction assertEdgesReferenceKnownNodes(nodes: GraphDiagramNode[], edges: GraphDiagramEdge[]): void {\n const ids = new Set(nodes.map((node) => node.id));\n for (const edge of edges) {\n if (!ids.has(edge.from)) {\n throw new Error(`GraphDiagram: edge \"${edge.id}\" references unknown node \"${edge.from}\"`);\n }\n if (!ids.has(edge.to)) {\n throw new Error(`GraphDiagram: edge \"${edge.id}\" references unknown node \"${edge.to}\"`);\n }\n }\n}\n\nfunction requireLevel(node: GraphDiagramNode): number {\n if (node.level === undefined || !Number.isFinite(node.level)) {\n throw new Error(`GraphDiagram: node \"${node.id}\" needs a finite level for the \"columns\" layout`);\n }\n return node.level;\n}\n\nfunction layoutNodes(\n nodes: GraphDiagramNode[],\n edges: GraphDiagramEdge[],\n { layout, nodeWidth, nodeHeight, columnGap, rowGap }: LayoutOptions,\n): ColumnsLayoutResult {\n switch (layout) {\n case \"ring\":\n return { ...ringLayout(nodes, { nodeWidth, nodeHeight }), groups: [] };\n case \"columns\":\n return columnsLayout(\n nodes.map((node) => ({\n id: node.id,\n level: requireLevel(node),\n ...(node.group !== undefined ? { group: node.group } : {}),\n })),\n edges,\n {\n nodeWidth,\n nodeHeight,\n ...(columnGap !== undefined ? { columnGap } : {}),\n ...(rowGap !== undefined ? { rowGap } : {}),\n },\n );\n default:\n throw new Error(`GraphDiagram: unknown layout \"${layout satisfies never}\"`);\n }\n}\n\nfunction toPercent(value: number, extent: number): string {\n return `${(value / extent) * 100}%`;\n}\n\nfunction stageStyle(size: { width: number; height: number }, natural: boolean, panZoom: PanZoom | undefined): CSSProperties {\n if (!natural) return { aspectRatio: `${size.width} / ${size.height}` };\n if (!panZoom) return size;\n const { x, y, scale } = panZoom.transform;\n return { ...size, transform: `translate(${x}px, ${y}px) scale(${scale})`, transformOrigin: \"0 0\" };\n}\n\n/** `resettable`: the diagram opens at another view than the whole of it, so there is one to return to. */\nfunction ZoomControls({ panZoom, resettable }: { panZoom: PanZoom; resettable: boolean }) {\n return (\n <div className=\"absolute right-2 top-2 flex cursor-default gap-0.5 rounded-md border border-border bg-background p-0.5 shadow-sm\">\n <IconButton icon={UiZoomOut} label=\"Zoom out\" className=\"size-6\" onClick={panZoom.zoomOut} />\n <IconButton icon={UiZoomIn} label=\"Zoom in\" className=\"size-6\" onClick={panZoom.zoomIn} />\n <IconButton icon={UiFullscreen} label=\"Fit to view\" className=\"size-6\" onClick={panZoom.fit} />\n {resettable && <IconButton icon={UiHome} label=\"Reset view\" className=\"size-6\" onClick={panZoom.reset} />}\n </div>\n );\n}\n\n/** How a zoomable diagram opens: no smaller than `fitMinScale`, centred on the `focusId` node. */\nfunction openingFit(\n positions: Record<string, GraphLayoutPosition>,\n fitMinScale: number | undefined,\n focusId: string | undefined,\n): FitOptions {\n return {\n ...(fitMinScale !== undefined ? { minScale: fitMinScale } : {}),\n ...(focusId !== undefined ? { focus: requireEntry(positions, focusId, \"layout position\") } : {}),\n };\n}\n\nexport function GraphDiagram({\n nodes,\n edges,\n layout = \"ring\",\n selectedId,\n onNodeSelect,\n onNodeExpand,\n selectedEdgeId,\n onEdgeSelect,\n edgeFocus = \"auto\",\n groups,\n nodeWidth = DEFAULT_NODE_WIDTH,\n nodeHeight = DEFAULT_NODE_HEIGHT,\n columnGap,\n rowGap,\n zoomable = false,\n fitMinScale,\n focusId,\n maxHeight,\n ariaLabel,\n className,\n}: GraphDiagramProps) {\n assertEdgesReferenceKnownNodes(nodes, edges);\n const markerPrefix = `graph-diagram-${useId().replace(/[^a-zA-Z0-9_-]/g, \"\")}`;\n\n const { width, height, positions, groups: groupBoxes } = useMemo(\n () => layoutNodes(nodes, edges, { layout, nodeWidth, nodeHeight, columnGap, rowGap }),\n [layout, nodes, edges, nodeWidth, nodeHeight, columnGap, rowGap],\n );\n const routes = useMemo(\n () =>\n routeEdges(edges, positions, { nodeWidth, nodeHeight }, { anchor: layout === \"columns\" ? \"side\" : \"center\" }),\n [edges, positions, nodeWidth, nodeHeight, layout],\n );\n\n const panZoom = usePanZoom({\n enabled: zoomable,\n contentWidth: width,\n contentHeight: height,\n opening: openingFit(positions, fitMinScale, focusId),\n });\n const natural = layout === \"columns\" || zoomable;\n const place: GraphPlacer = natural\n ? ({ x, y }) => ({ left: x, top: y })\n : ({ x, y }) => ({ left: toPercent(x, width), top: toPercent(y, height) });\n const focus = useEdgeFocus({ mode: edgeFocus, edges, selectedId, selectedEdgeId });\n const edgeSelection = { selectedEdgeId, onEdgeSelect, focus: focus.state };\n\n return (\n <div\n ref={panZoom.viewportRef}\n className={cn(\n \"w-full\",\n zoomable ? \"relative touch-none overflow-hidden\" : \"overflow-auto\",\n zoomable && (panZoom.panning ? \"cursor-grabbing select-none\" : \"cursor-grab\"),\n className,\n )}\n style={maxHeight != null ? { maxHeight } : undefined}\n {...panZoom.handlers}\n >\n <div\n ref={panZoom.contentRef}\n data-graph-stage=\"\"\n className={cn(\"relative\", natural ? !zoomable && \"mx-auto\" : \"w-full\")}\n style={stageStyle({ width, height }, natural, zoomable ? panZoom : undefined)}\n >\n <GraphDiagramGroupBoxes boxes={groupBoxes} groups={groups} />\n <GraphDiagramEdgePaths\n edges={edges}\n nodes={nodes}\n routes={routes}\n width={width}\n height={height}\n ariaLabel={ariaLabel}\n markerPrefix={markerPrefix}\n onEdgeHover={focus.onEdgeHover}\n {...edgeSelection}\n />\n <div className=\"pointer-events-none absolute inset-0\">\n <GraphDiagramEdgeLabels edges={edges} routes={routes} place={place} spread={natural} {...edgeSelection} />\n <GraphDiagramNodes\n nodes={nodes}\n positions={positions}\n place={place}\n nodeWidth={nodeWidth}\n nodeHeight={nodeHeight}\n selectedId={selectedId}\n onNodeSelect={onNodeSelect}\n onNodeExpand={onNodeExpand}\n onNodeHover={focus.onNodeHover}\n />\n </div>\n </div>\n {zoomable && <ZoomControls panZoom={panZoom} resettable={fitMinScale !== undefined} />}\n </div>\n );\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"GraphDiagram.js","sources":["../../src/data/GraphDiagram.tsx"],"sourcesContent":["import { useId, useMemo, type CSSProperties } from \"react\";\nimport { cn } from \"../lib/utils\";\nimport { IconButton } from \"../components/IconButton\";\nimport { UiFullscreen, UiHome, UiZoomIn, UiZoomOut } from \"../icons\";\nimport { columnsLayout, type ColumnsLayoutResult } from \"./graph-columns-layout\";\nimport { ringLayout, routeEdges, type GraphLayoutPosition } from \"./graph-layout\";\nimport { GraphDiagramEdgeLabels, GraphDiagramEdgePaths } from \"./GraphDiagramEdges\";\nimport { GraphDiagramGroupBoxes } from \"./GraphDiagramGroups\";\nimport { GraphDiagramNodes } from \"./GraphDiagramNodes\";\nimport { useGroupWindows } from \"./use-group-windows\";\nimport {\n requireEntry,\n type GraphDiagramEdge,\n type GraphDiagramEdgeFocus,\n type GraphDiagramGroup,\n type GraphDiagramLayout,\n type GraphDiagramNode,\n type GraphPlacer,\n} from \"./graph-diagram-model\";\nimport { useEdgeFocus } from \"./use-edge-focus\";\nimport { usePanZoom, type FitOptions, type PanZoom, type WheelMode } from \"./use-pan-zoom\";\n\nexport type {\n GraphDiagramEdge,\n GraphDiagramEdgeFocus,\n GraphDiagramGroup,\n GraphDiagramLayout,\n GraphDiagramNode,\n} from \"./graph-diagram-model\";\n\n// GraphDiagram renders a generic, type-agnostic node/edge diagram. It knows\n// nothing about the domain: a producer maps its data into\n// GraphDiagramNode/GraphDiagramEdge and gets layout, edge routing and\n// selection behaviour.\n//\n// \"ring\" suits a small cycle of resources and processes — relationships with\n// back edges or reciprocal pairs. \"columns\" suits a directed graph with a\n// natural depth (a call graph, a dependency chain): nodes sit in the column of\n// their `level`, grouped and boxed by `group`.\n//\n// The \"columns\" layout, and any zoomable diagram, is drawn at its natural\n// pixel size so node boxes, edges and group boxes share one coordinate system\n// at every container width and zoom level. A non-zoomable \"ring\" keeps scaling\n// its node positions to the container width.\n\nexport interface GraphDiagramProps {\n nodes: GraphDiagramNode[];\n edges: GraphDiagramEdge[];\n /** Defaults to \"ring\". \"columns\" needs a `level` on every node. */\n layout?: GraphDiagramLayout;\n selectedId?: string;\n onNodeSelect?: (id: string) => void;\n /** Called by a node's `+N` control (see `expandCount`); does not select the node. */\n onNodeExpand?: (id: string) => void;\n selectedEdgeId?: string;\n /** Makes edges, and their label pills, selectable. */\n onEdgeSelect?: (id: string) => void;\n /**\n * Whether an edge shows its pill only while in focus, and fades while another is. Defaults to\n * \"auto\": a diagram with more than 32 edges is focused, a smaller one shows everything.\n */\n edgeFocus?: GraphDiagramEdgeFocus;\n /**\n * \"columns\" layout: captions for the group rectangles. A group without an entry shows its id. A group\n * with more than `GROUP_MEMBER_WINDOW` members in a column scrolls them in a window that many rows tall.\n */\n groups?: GraphDiagramGroup[];\n /** \"columns\" layout: the chevron of a group whose `collapsed` is set asks to collapse or expand it. */\n onGroupToggle?: (groupId: string) => void;\n nodeWidth?: number;\n nodeHeight?: number;\n /**\n * \"columns\" layout: the height of a node with `size: \"compact\"`, drawn on one line. A group of only\n * compact nodes stacks them closer and pads them tighter. Defaults to 24.\n */\n compactNodeHeight?: number;\n /** \"columns\" layout: height of a record group's header in px. Defaults to 24. */\n recordHeaderHeight?: number;\n /** \"columns\" layout: horizontal gap between columns in px. Leave room for edge label pills. */\n columnGap?: number;\n /** \"columns\" layout: vertical gap between stacked nodes in px. */\n rowGap?: number;\n /** Ctrl/meta + wheel (or pinch) zooms, dragging the background pans, and zoom controls appear. */\n zoomable?: boolean;\n /** Zoomable: \"zoom\" makes a plain mouse wheel zoom too, for a diagram that fills its pane. Defaults to \"modifier\". */\n wheelZoom?: WheelMode;\n /**\n * Zoomable: the smallest scale the diagram opens at, so its text stays readable. A diagram too\n * large for it opens overflowing, centred on `focusId`, and is panned to reach the rest. `Fit to\n * view` still shows everything, and `Reset view` returns here. Unset, the diagram opens whole.\n */\n fitMinScale?: number;\n /** Zoomable: the node an overflowing diagram opens centred on. Defaults to the diagram's centre. */\n focusId?: string;\n maxHeight?: number | string;\n ariaLabel: string;\n className?: string;\n}\n\nconst DEFAULT_NODE_WIDTH = 168;\nconst DEFAULT_NODE_HEIGHT = 60;\nconst DEFAULT_COMPACT_NODE_HEIGHT = 24;\n\ninterface LayoutOptions {\n layout: GraphDiagramLayout;\n nodeWidth: number;\n nodeHeight: number;\n compactNodeHeight: number;\n records: readonly string[];\n collapsed: readonly string[];\n recordHeaderHeight: number;\n columnGap: number | undefined;\n rowGap: number | undefined;\n}\n\n/**\n * The heights of the nodes not drawn at the node height, in the \"columns\" layout: the compact ones, and\n * the stand-ins of collapsed groups, as tall as the header they are drawn as.\n */\nfunction compactHeights(nodes: GraphDiagramNode[], layout: GraphDiagramLayout, compactNodeHeight: number, standIns: ReadonlySet<string>, headerHeight: number): Record<string, number> {\n if (layout !== \"columns\") return {};\n return Object.fromEntries(nodes.flatMap((node): [string, number][] => {\n if (standIns.has(node.id)) return [[node.id, headerHeight]];\n return node.size === \"compact\" ? [[node.id, compactNodeHeight]] : [];\n }));\n}\n\n/** The one node each collapsed group holds, by group id. */\nfunction collapsedStandIns(nodes: GraphDiagramNode[], groups: GraphDiagramGroup[] | undefined): Map<string, string> {\n const collapsed = new Set(groups?.filter((group) => group.collapsed === true).map((group) => group.id));\n const standIns = new Map<string, string>();\n for (const node of nodes) {\n if (node.group === undefined || !collapsed.has(node.group)) continue;\n const held = standIns.get(node.group);\n if (held !== undefined) throw new Error(`GraphDiagram: collapsed group \"${node.group}\" holds \"${held}\" and \"${node.id}\"; it draws one stand-in`);\n standIns.set(node.group, node.id);\n }\n return standIns;\n}\n\nfunction assertEdgesReferenceKnownNodes(nodes: GraphDiagramNode[], edges: GraphDiagramEdge[]): void {\n const ids = new Set(nodes.map((node) => node.id));\n for (const edge of edges) {\n if (!ids.has(edge.from)) {\n throw new Error(`GraphDiagram: edge \"${edge.id}\" references unknown node \"${edge.from}\"`);\n }\n if (!ids.has(edge.to)) {\n throw new Error(`GraphDiagram: edge \"${edge.id}\" references unknown node \"${edge.to}\"`);\n }\n }\n}\n\nfunction requireLevel(node: GraphDiagramNode): number {\n if (node.level === undefined || !Number.isFinite(node.level)) {\n throw new Error(`GraphDiagram: node \"${node.id}\" needs a finite level for the \"columns\" layout`);\n }\n return node.level;\n}\n\nfunction layoutNodes(\n nodes: GraphDiagramNode[],\n edges: GraphDiagramEdge[],\n { layout, nodeWidth, nodeHeight, compactNodeHeight, records, collapsed, recordHeaderHeight, columnGap, rowGap }: LayoutOptions,\n): ColumnsLayoutResult {\n switch (layout) {\n case \"ring\":\n return { ...ringLayout(nodes, { nodeWidth, nodeHeight }), groups: [] };\n case \"columns\":\n return columnsLayout(\n nodes.map((node) => ({\n id: node.id,\n level: requireLevel(node),\n ...(node.group !== undefined ? { group: node.group } : {}),\n ...(node.size === \"compact\" ? { compact: true } : {}),\n })),\n edges,\n {\n nodeWidth,\n nodeHeight,\n compactNodeHeight,\n records,\n collapsed,\n recordHeaderHeight,\n ...(columnGap !== undefined ? { columnGap } : {}),\n ...(rowGap !== undefined ? { rowGap } : {}),\n },\n );\n default:\n throw new Error(`GraphDiagram: unknown layout \"${layout satisfies never}\"`);\n }\n}\n\nfunction toPercent(value: number, extent: number): string {\n return `${(value / extent) * 100}%`;\n}\n\nfunction stageStyle(size: { width: number; height: number }, natural: boolean, panZoom: PanZoom | undefined): CSSProperties {\n if (!natural) return { aspectRatio: `${size.width} / ${size.height}` };\n if (!panZoom) return size;\n const { x, y, scale } = panZoom.transform;\n return { ...size, transform: `translate(${x}px, ${y}px) scale(${scale})`, transformOrigin: \"0 0\" };\n}\n\n/** `resettable`: the diagram opens at another view than the whole of it, so there is one to return to. */\nfunction ZoomControls({ panZoom, resettable }: { panZoom: PanZoom; resettable: boolean }) {\n return (\n <div className=\"absolute right-2 top-2 flex cursor-default gap-0.5 rounded-md border border-border bg-background p-0.5 shadow-sm\">\n <IconButton icon={UiZoomOut} label=\"Zoom out\" className=\"size-6\" onClick={panZoom.zoomOut} />\n <IconButton icon={UiZoomIn} label=\"Zoom in\" className=\"size-6\" onClick={panZoom.zoomIn} />\n <IconButton icon={UiFullscreen} label=\"Fit to view\" className=\"size-6\" onClick={panZoom.fit} />\n {resettable && <IconButton icon={UiHome} label=\"Reset view\" className=\"size-6\" onClick={panZoom.reset} />}\n </div>\n );\n}\n\n/** How a zoomable diagram opens: no smaller than `fitMinScale`, centred on the `focusId` node. */\nfunction openingFit(\n positions: Record<string, GraphLayoutPosition>,\n fitMinScale: number | undefined,\n focusId: string | undefined,\n): FitOptions {\n return {\n ...(fitMinScale !== undefined ? { minScale: fitMinScale } : {}),\n ...(focusId !== undefined ? { focus: requireEntry(positions, focusId, \"layout position\") } : {}),\n };\n}\n\nexport function GraphDiagram({\n nodes,\n edges,\n layout = \"ring\",\n selectedId,\n onNodeSelect,\n onNodeExpand,\n selectedEdgeId,\n onEdgeSelect,\n edgeFocus = \"auto\",\n groups,\n onGroupToggle,\n nodeWidth = DEFAULT_NODE_WIDTH,\n nodeHeight = DEFAULT_NODE_HEIGHT,\n compactNodeHeight = DEFAULT_COMPACT_NODE_HEIGHT,\n recordHeaderHeight = 24,\n columnGap,\n rowGap,\n zoomable = false,\n wheelZoom = \"modifier\",\n fitMinScale,\n focusId,\n maxHeight,\n ariaLabel,\n className,\n}: GraphDiagramProps) {\n assertEdgesReferenceKnownNodes(nodes, edges);\n const markerPrefix = `graph-diagram-${useId().replace(/[^a-zA-Z0-9_-]/g, \"\")}`;\n const records = useMemo(() => groups?.filter((group) => group.variant === \"record\").map((group) => group.id) ?? [], [groups]);\n const recordNodes = useMemo(() => new Set(layout === \"columns\" ? nodes.filter((node) => node.group !== undefined && records.includes(node.group)).map((node) => node.id) : []), [layout, nodes, records]);\n const standIns = useMemo(() => (layout === \"columns\" ? collapsedStandIns(nodes, groups) : new Map<string, string>()), [layout, nodes, groups]);\n const collapsed = useMemo(() => [...standIns.keys()], [standIns]);\n\n const { width, height, positions: laidOut, groups: groupBoxes } = useMemo(\n () => layoutNodes(nodes, edges, { layout, nodeWidth, nodeHeight, compactNodeHeight, records, collapsed, recordHeaderHeight, columnGap, rowGap }),\n [layout, nodes, edges, nodeWidth, nodeHeight, compactNodeHeight, records, collapsed, recordHeaderHeight, columnGap, rowGap],\n );\n const nodeHeights = useMemo(\n () => compactHeights(nodes, layout, compactNodeHeight, new Set(standIns.values()), recordHeaderHeight),\n [nodes, layout, compactNodeHeight, standIns, recordHeaderHeight],\n );\n\n const panZoom = usePanZoom({\n enabled: zoomable,\n wheel: wheelZoom,\n contentWidth: width,\n contentHeight: height,\n opening: openingFit(laidOut, fitMinScale, focusId),\n });\n const windows = useGroupWindows({ boxes: groupBoxes, positions: laidOut, reveal: selectedId ?? focusId, stageRef: panZoom.contentRef, scale: zoomable ? panZoom.transform.scale : 1 });\n const { positions } = windows;\n const routes = useMemo(\n () =>\n routeEdges(edges, positions, { nodeWidth, nodeHeight, nodeHeights }, { anchor: layout === \"columns\" ? \"side\" : \"center\" }),\n [edges, positions, nodeWidth, nodeHeight, nodeHeights, layout],\n );\n const drawnNodes = useMemo(() => {\n const standing = new Set(standIns.values());\n return nodes.filter((node) => !windows.hidden.has(node.id) && !standing.has(node.id));\n }, [nodes, windows.hidden, standIns]);\n const windowOf = useMemo(\n () => new Map(groupBoxes.flatMap((box) => (box.window ? box.window.members.map((id): [string, string] => [id, box.id]) : []))),\n [groupBoxes],\n );\n const natural = layout === \"columns\" || zoomable;\n const place: GraphPlacer = natural\n ? ({ x, y }) => ({ left: x, top: y })\n : ({ x, y }) => ({ left: toPercent(x, width), top: toPercent(y, height) });\n const focus = useEdgeFocus({ mode: edgeFocus, edges, selectedId, selectedEdgeId });\n const edgeSelection = { selectedEdgeId, onEdgeSelect, focus: focus.state };\n\n return (\n <div\n ref={panZoom.viewportRef}\n className={cn(\n \"w-full\",\n zoomable ? \"relative touch-none overflow-hidden\" : \"overflow-auto\",\n zoomable && (panZoom.panning ? \"cursor-grabbing select-none\" : \"cursor-grab\"),\n className,\n )}\n style={maxHeight != null ? { maxHeight } : undefined}\n {...panZoom.handlers}\n >\n <div\n ref={panZoom.contentRef}\n data-graph-stage=\"\"\n className={cn(\"relative\", natural ? !zoomable && \"mx-auto\" : \"w-full\")}\n style={stageStyle({ width, height }, natural, zoomable ? panZoom : undefined)}\n >\n <GraphDiagramGroupBoxes boxes={groupBoxes} groups={groups} starts={windows.starts} onScroll={windows.scroll} onGroupToggle={onGroupToggle}\n standIns={standIns} selectedId={selectedId} onNodeSelect={onNodeSelect} />\n <GraphDiagramEdgePaths\n edges={edges}\n nodes={nodes}\n routes={routes}\n width={width}\n height={height}\n ariaLabel={ariaLabel}\n markerPrefix={markerPrefix}\n onEdgeHover={focus.onEdgeHover}\n {...edgeSelection}\n />\n <div className=\"pointer-events-none absolute inset-0\">\n <GraphDiagramEdgeLabels edges={edges} routes={routes} place={place} spread={natural} {...edgeSelection} />\n <GraphDiagramNodes\n nodes={drawnNodes}\n positions={positions}\n windowOf={windowOf}\n place={place}\n nodeWidth={nodeWidth}\n nodeHeight={nodeHeight}\n nodeHeights={nodeHeights}\n recordNodes={recordNodes}\n selectedId={selectedId}\n onNodeSelect={onNodeSelect}\n onNodeExpand={onNodeExpand}\n onNodeHover={focus.onNodeHover}\n />\n </div>\n </div>\n {zoomable && <ZoomControls panZoom={panZoom} resettable={fitMinScale !== undefined} />}\n </div>\n );\n}\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,100 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const jsxRuntime = require("react/jsx-runtime");
4
+ const IconButton = require("../components/IconButton.cjs");
5
+ const utils = require("../lib/utils.cjs");
6
+ const graphGroupWindow = require("./graph-group-window.cjs");
7
+ const graphDiagramModel = require("./graph-diagram-model.cjs");
8
+ const UiChevronRight = require("../icons/components/UiChevronRight.cjs");
9
+ const UiChevronDown = require("../icons/components/UiChevronDown.cjs");
10
+ const UiChevronUp = require("../icons/components/UiChevronUp.cjs");
11
+ function Chevron({ group, name, onToggle }) {
12
+ const collapsed = group.collapsed === true;
13
+ return /* @__PURE__ */ jsxRuntime.jsx(
14
+ IconButton.IconButton,
15
+ {
16
+ icon: collapsed ? UiChevronRight.UiChevronRight : UiChevronDown.UiChevronDown,
17
+ label: `${collapsed ? "Expand" : "Collapse"} ${name}`,
18
+ "aria-expanded": !collapsed,
19
+ className: "pointer-events-auto size-4",
20
+ onClick: onToggle
21
+ }
22
+ );
23
+ }
24
+ function Header({ box, caption, title, chevron, aside, select }) {
25
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-graph-record-header": "", title, className: "pointer-events-auto flex items-center gap-1 bg-muted px-1.5 text-[11px] font-semibold", style: { height: box.headerHeight }, children: [
26
+ chevron,
27
+ select ? /* @__PURE__ */ jsxRuntime.jsx(
28
+ "button",
29
+ {
30
+ type: "button",
31
+ "aria-label": `Select ${select.name}`,
32
+ "aria-pressed": select.selected,
33
+ onClick: select.onSelect,
34
+ className: utils.cn("min-w-0 truncate rounded-sm text-left hover:underline focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring", select.selected && "text-primary"),
35
+ children: caption
36
+ }
37
+ ) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "min-w-0 truncate", children: caption }),
38
+ aside != null && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ml-auto shrink-0 pl-2 text-[10px] font-normal text-muted-foreground", children: aside })
39
+ ] });
40
+ }
41
+ function WindowFooter({ box, rows, start, name, onScroll }) {
42
+ const { first, last, total } = graphGroupWindow.windowRows(rows, start);
43
+ return /* @__PURE__ */ jsxRuntime.jsxs(
44
+ "div",
45
+ {
46
+ "data-graph-window-footer": "",
47
+ className: "pointer-events-auto absolute inset-x-0 flex items-center gap-1 px-2 text-[10px] text-muted-foreground",
48
+ style: { top: rows.top + rows.height - box.y, height: rows.footerHeight },
49
+ children: [
50
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "min-w-0 flex-1 truncate tabular-nums", children: [
51
+ "rows ",
52
+ first,
53
+ "–",
54
+ last,
55
+ " of ",
56
+ total
57
+ ] }),
58
+ /* @__PURE__ */ jsxRuntime.jsx(IconButton.IconButton, { icon: UiChevronUp.UiChevronUp, label: `Scroll ${name} up`, className: "size-4", disabled: first === 1, onClick: () => onScroll(-rows.rows) }),
59
+ /* @__PURE__ */ jsxRuntime.jsx(IconButton.IconButton, { icon: UiChevronDown.UiChevronDown, label: `Scroll ${name} down`, className: "size-4", disabled: last === total, onClick: () => onScroll(rows.rows) })
60
+ ]
61
+ }
62
+ );
63
+ }
64
+ function GraphDiagramGroupBoxes({ boxes, groups, starts, onScroll, onGroupToggle, standIns, selectedId, onNodeSelect }) {
65
+ const entries = new Map(groups == null ? void 0 : groups.map((group) => [group.id, group]));
66
+ return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: boxes.map((box) => {
67
+ const group = entries.get(box.group);
68
+ const name = graphDiagramModel.groupName(group, box.group);
69
+ const caption = group ? group.label : box.group;
70
+ const chevron = group && group.collapsed !== void 0 && onGroupToggle ? /* @__PURE__ */ jsxRuntime.jsx(Chevron, { group, name, onToggle: () => onGroupToggle(box.group) }) : null;
71
+ const standIn = box.collapsed ? standIns.get(box.group) : void 0;
72
+ const select = standIn !== void 0 && onNodeSelect ? { name, selected: selectedId === standIn, onSelect: () => onNodeSelect(standIn) } : void 0;
73
+ return /* @__PURE__ */ jsxRuntime.jsxs(
74
+ "div",
75
+ {
76
+ "data-graph-group": box.id,
77
+ "data-graph-group-variant": box.record ? "record" : "box",
78
+ ...box.collapsed ? { "data-graph-group-collapsed": "" } : {},
79
+ ...box.window ? { "data-graph-window": box.id } : {},
80
+ className: utils.cn(
81
+ "absolute border border-border",
82
+ box.window ? "pointer-events-auto" : "pointer-events-none",
83
+ box.record || box.collapsed ? "overflow-hidden rounded-md bg-card shadow-sm" : "rounded-xl bg-muted/30",
84
+ !box.record && "border-dashed"
85
+ ),
86
+ style: { left: box.x, top: box.y, width: box.width, height: box.height },
87
+ children: [
88
+ box.record || box.collapsed ? /* @__PURE__ */ jsxRuntime.jsx(Header, { box, caption, title: group == null ? void 0 : group.title, chevron, aside: group == null ? void 0 : group.aside, select }) : /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "pointer-events-auto absolute left-2 top-0 flex max-w-[calc(100%-1rem)] -translate-y-1/2 items-center gap-0.5 rounded border border-border bg-background px-1.5 text-[10px] font-medium leading-4 text-muted-foreground", children: [
89
+ chevron,
90
+ /* @__PURE__ */ jsxRuntime.jsx("span", { title: group == null ? void 0 : group.title, className: "pointer-events-auto min-w-0 truncate", children: caption })
91
+ ] }),
92
+ box.window && /* @__PURE__ */ jsxRuntime.jsx(WindowFooter, { box, rows: box.window, start: starts[box.id] ?? 0, name, onScroll: (rows) => onScroll(box.id, rows) })
93
+ ]
94
+ },
95
+ box.id
96
+ );
97
+ }) });
98
+ }
99
+ exports.GraphDiagramGroupBoxes = GraphDiagramGroupBoxes;
100
+ //# sourceMappingURL=GraphDiagramGroups.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GraphDiagramGroups.cjs","sources":["../../src/data/GraphDiagramGroups.tsx"],"sourcesContent":["import type { ReactNode } from \"react\";\nimport { IconButton } from \"../components/IconButton\";\nimport { UiChevronDown, UiChevronRight, UiChevronUp } from \"../icons\";\nimport { cn } from \"../lib/utils\";\nimport type { GraphLayoutGroupBox, GroupMemberWindow } from \"./graph-columns-layout\";\nimport { windowRows, type WindowStarts } from \"./graph-group-window\";\nimport { groupName, type GraphDiagramGroup } from \"./graph-diagram-model\";\n\nexport interface GraphDiagramGroupBoxesProps {\n boxes: GraphLayoutGroupBox[];\n groups: GraphDiagramGroup[] | undefined;\n /** Window starts by box id. */\n starts: WindowStarts;\n onScroll: (boxId: string, rows: number) => void;\n /** Shows a chevron on every group whose `collapsed` is set. */\n onGroupToggle: ((groupId: string) => void) | undefined;\n /** The stand-in node of each collapsed group, by group id: its header selects it. */\n standIns: ReadonlyMap<string, string>;\n selectedId: string | undefined;\n onNodeSelect: ((id: string) => void) | undefined;\n}\n\nfunction Chevron({ group, name, onToggle }: { group: GraphDiagramGroup; name: string; onToggle: () => void }) {\n const collapsed = group.collapsed === true;\n return (\n <IconButton icon={collapsed ? UiChevronRight : UiChevronDown} label={`${collapsed ? \"Expand\" : \"Collapse\"} ${name}`} aria-expanded={!collapsed}\n className=\"pointer-events-auto size-4\" onClick={onToggle} />\n );\n}\n\n/** A record's header, or a collapsed group's whole box: chevron, caption, and what it holds. */\nfunction Header({ box, caption, title, chevron, aside, select }: {\n box: GraphLayoutGroupBox;\n caption: ReactNode;\n title: string | undefined;\n chevron: ReactNode;\n aside: ReactNode;\n select: { name: string; selected: boolean; onSelect: () => void } | undefined;\n}) {\n return (\n <div data-graph-record-header=\"\" title={title} className=\"pointer-events-auto flex items-center gap-1 bg-muted px-1.5 text-[11px] font-semibold\" style={{ height: box.headerHeight }}>\n {chevron}\n {select ? (\n <button type=\"button\" aria-label={`Select ${select.name}`} aria-pressed={select.selected} onClick={select.onSelect}\n className={cn(\"min-w-0 truncate rounded-sm text-left hover:underline focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\", select.selected && \"text-primary\")}>\n {caption}\n </button>\n ) : <span className=\"min-w-0 truncate\">{caption}</span>}\n {aside != null && <span className=\"ml-auto shrink-0 pl-2 text-[10px] font-normal text-muted-foreground\">{aside}</span>}\n </div>\n );\n}\n\n/** \"rows a–b of n\" under a windowed group's rows, with buttons that page it. */\nfunction WindowFooter({ box, rows, start, name, onScroll }: { box: GraphLayoutGroupBox; rows: GroupMemberWindow; start: number; name: string; onScroll: (rows: number) => void }) {\n const { first, last, total } = windowRows(rows, start);\n return (\n <div data-graph-window-footer=\"\" className=\"pointer-events-auto absolute inset-x-0 flex items-center gap-1 px-2 text-[10px] text-muted-foreground\"\n style={{ top: rows.top + rows.height - box.y, height: rows.footerHeight }}>\n <span className=\"min-w-0 flex-1 truncate tabular-nums\">rows {first}–{last} of {total}</span>\n <IconButton icon={UiChevronUp} label={`Scroll ${name} up`} className=\"size-4\" disabled={first === 1} onClick={() => onScroll(-rows.rows)} />\n <IconButton icon={UiChevronDown} label={`Scroll ${name} down`} className=\"size-4\" disabled={last === total} onClick={() => onScroll(rows.rows)} />\n </div>\n );\n}\n\n/**\n * Group rectangles, drawn behind the edges and nodes. A record is captioned by a header, a box on its top\n * border; a collapsed group is its header alone. A box lets the pointer through to the stage, so a click\n * inside it never lands on the box; only its caption, chevron and footer take the pointer. A windowed box\n * takes the wheel too, to scroll its members.\n */\nexport function GraphDiagramGroupBoxes({ boxes, groups, starts, onScroll, onGroupToggle, standIns, selectedId, onNodeSelect }: GraphDiagramGroupBoxesProps) {\n const entries = new Map(groups?.map((group) => [group.id, group]));\n return (\n <>\n {boxes.map((box) => {\n const group = entries.get(box.group);\n const name = groupName(group, box.group);\n const caption = group ? group.label : box.group;\n const chevron = group && group.collapsed !== undefined && onGroupToggle ? <Chevron group={group} name={name} onToggle={() => onGroupToggle(box.group)} /> : null;\n const standIn = box.collapsed ? standIns.get(box.group) : undefined;\n const select = standIn !== undefined && onNodeSelect ? { name, selected: selectedId === standIn, onSelect: () => onNodeSelect(standIn) } : undefined;\n return (\n <div\n key={box.id}\n data-graph-group={box.id}\n data-graph-group-variant={box.record ? \"record\" : \"box\"}\n {...(box.collapsed ? { \"data-graph-group-collapsed\": \"\" } : {})}\n {...(box.window ? { \"data-graph-window\": box.id } : {})}\n className={cn(\n \"absolute border border-border\",\n box.window ? \"pointer-events-auto\" : \"pointer-events-none\",\n box.record || box.collapsed ? \"overflow-hidden rounded-md bg-card shadow-sm\" : \"rounded-xl bg-muted/30\",\n !box.record && \"border-dashed\",\n )}\n style={{ left: box.x, top: box.y, width: box.width, height: box.height }}\n >\n {box.record || box.collapsed ? (\n <Header box={box} caption={caption} title={group?.title} chevron={chevron} aside={group?.aside} select={select} />\n ) : (\n <span className=\"pointer-events-auto absolute left-2 top-0 flex max-w-[calc(100%-1rem)] -translate-y-1/2 items-center gap-0.5 rounded border border-border bg-background px-1.5 text-[10px] font-medium leading-4 text-muted-foreground\">\n {chevron}\n <span title={group?.title} className=\"pointer-events-auto min-w-0 truncate\">{caption}</span>\n </span>\n )}\n {box.window && <WindowFooter box={box} rows={box.window} start={starts[box.id] ?? 0} name={name} onScroll={(rows) => onScroll(box.id, rows)} />}\n </div>\n );\n })}\n </>\n );\n}\n"],"names":["jsx","IconButton","UiChevronRight","UiChevronDown","jsxs","cn","windowRows","UiChevronUp","Fragment","groupName"],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ import { GraphLayoutGroupBox } from './graph-columns-layout.js';
2
+ import { WindowStarts } from './graph-group-window.js';
3
+ import { GraphDiagramGroup } from './graph-diagram-model.js';
4
+ export interface GraphDiagramGroupBoxesProps {
5
+ boxes: GraphLayoutGroupBox[];
6
+ groups: GraphDiagramGroup[] | undefined;
7
+ /** Window starts by box id. */
8
+ starts: WindowStarts;
9
+ onScroll: (boxId: string, rows: number) => void;
10
+ /** Shows a chevron on every group whose `collapsed` is set. */
11
+ onGroupToggle: ((groupId: string) => void) | undefined;
12
+ /** The stand-in node of each collapsed group, by group id: its header selects it. */
13
+ standIns: ReadonlyMap<string, string>;
14
+ selectedId: string | undefined;
15
+ onNodeSelect: ((id: string) => void) | undefined;
16
+ }
17
+ /**
18
+ * Group rectangles, drawn behind the edges and nodes. A record is captioned by a header, a box on its top
19
+ * border; a collapsed group is its header alone. A box lets the pointer through to the stage, so a click
20
+ * inside it never lands on the box; only its caption, chevron and footer take the pointer. A windowed box
21
+ * takes the wheel too, to scroll its members.
22
+ */
23
+ export declare function GraphDiagramGroupBoxes({ boxes, groups, starts, onScroll, onGroupToggle, standIns, selectedId, onNodeSelect }: GraphDiagramGroupBoxesProps): import("react").JSX.Element;
24
+ //# sourceMappingURL=GraphDiagramGroups.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GraphDiagramGroups.d.ts","sourceRoot":"","sources":["../../src/data/GraphDiagramGroups.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,mBAAmB,EAAqB,MAAM,wBAAwB,CAAC;AACrF,OAAO,EAAc,KAAK,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACrE,OAAO,EAAa,KAAK,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAE1E,MAAM,WAAW,2BAA2B;IAC1C,KAAK,EAAE,mBAAmB,EAAE,CAAC;IAC7B,MAAM,EAAE,iBAAiB,EAAE,GAAG,SAAS,CAAC;IACxC,+BAA+B;IAC/B,MAAM,EAAE,YAAY,CAAC;IACrB,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAChD,+DAA+D;IAC/D,aAAa,EAAE,CAAC,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;IACvD,qFAAqF;IACrF,QAAQ,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACtC,UAAU,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B,YAAY,EAAE,CAAC,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;CAClD;AA8CD;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,aAAa,EAAE,QAAQ,EAAE,UAAU,EAAE,YAAY,EAAE,EAAE,2BAA2B,+BAwCzJ"}
@@ -0,0 +1,100 @@
1
+ import { jsx, Fragment, jsxs } from "react/jsx-runtime";
2
+ import { IconButton } from "../components/IconButton.js";
3
+ import { cn } from "../lib/utils.js";
4
+ import { windowRows } from "./graph-group-window.js";
5
+ import { groupName } from "./graph-diagram-model.js";
6
+ import { UiChevronRight } from "../icons/components/UiChevronRight.js";
7
+ import { UiChevronDown } from "../icons/components/UiChevronDown.js";
8
+ import { UiChevronUp } from "../icons/components/UiChevronUp.js";
9
+ function Chevron({ group, name, onToggle }) {
10
+ const collapsed = group.collapsed === true;
11
+ return /* @__PURE__ */ jsx(
12
+ IconButton,
13
+ {
14
+ icon: collapsed ? UiChevronRight : UiChevronDown,
15
+ label: `${collapsed ? "Expand" : "Collapse"} ${name}`,
16
+ "aria-expanded": !collapsed,
17
+ className: "pointer-events-auto size-4",
18
+ onClick: onToggle
19
+ }
20
+ );
21
+ }
22
+ function Header({ box, caption, title, chevron, aside, select }) {
23
+ return /* @__PURE__ */ jsxs("div", { "data-graph-record-header": "", title, className: "pointer-events-auto flex items-center gap-1 bg-muted px-1.5 text-[11px] font-semibold", style: { height: box.headerHeight }, children: [
24
+ chevron,
25
+ select ? /* @__PURE__ */ jsx(
26
+ "button",
27
+ {
28
+ type: "button",
29
+ "aria-label": `Select ${select.name}`,
30
+ "aria-pressed": select.selected,
31
+ onClick: select.onSelect,
32
+ className: cn("min-w-0 truncate rounded-sm text-left hover:underline focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring", select.selected && "text-primary"),
33
+ children: caption
34
+ }
35
+ ) : /* @__PURE__ */ jsx("span", { className: "min-w-0 truncate", children: caption }),
36
+ aside != null && /* @__PURE__ */ jsx("span", { className: "ml-auto shrink-0 pl-2 text-[10px] font-normal text-muted-foreground", children: aside })
37
+ ] });
38
+ }
39
+ function WindowFooter({ box, rows, start, name, onScroll }) {
40
+ const { first, last, total } = windowRows(rows, start);
41
+ return /* @__PURE__ */ jsxs(
42
+ "div",
43
+ {
44
+ "data-graph-window-footer": "",
45
+ className: "pointer-events-auto absolute inset-x-0 flex items-center gap-1 px-2 text-[10px] text-muted-foreground",
46
+ style: { top: rows.top + rows.height - box.y, height: rows.footerHeight },
47
+ children: [
48
+ /* @__PURE__ */ jsxs("span", { className: "min-w-0 flex-1 truncate tabular-nums", children: [
49
+ "rows ",
50
+ first,
51
+ "–",
52
+ last,
53
+ " of ",
54
+ total
55
+ ] }),
56
+ /* @__PURE__ */ jsx(IconButton, { icon: UiChevronUp, label: `Scroll ${name} up`, className: "size-4", disabled: first === 1, onClick: () => onScroll(-rows.rows) }),
57
+ /* @__PURE__ */ jsx(IconButton, { icon: UiChevronDown, label: `Scroll ${name} down`, className: "size-4", disabled: last === total, onClick: () => onScroll(rows.rows) })
58
+ ]
59
+ }
60
+ );
61
+ }
62
+ function GraphDiagramGroupBoxes({ boxes, groups, starts, onScroll, onGroupToggle, standIns, selectedId, onNodeSelect }) {
63
+ const entries = new Map(groups == null ? void 0 : groups.map((group) => [group.id, group]));
64
+ return /* @__PURE__ */ jsx(Fragment, { children: boxes.map((box) => {
65
+ const group = entries.get(box.group);
66
+ const name = groupName(group, box.group);
67
+ const caption = group ? group.label : box.group;
68
+ const chevron = group && group.collapsed !== void 0 && onGroupToggle ? /* @__PURE__ */ jsx(Chevron, { group, name, onToggle: () => onGroupToggle(box.group) }) : null;
69
+ const standIn = box.collapsed ? standIns.get(box.group) : void 0;
70
+ const select = standIn !== void 0 && onNodeSelect ? { name, selected: selectedId === standIn, onSelect: () => onNodeSelect(standIn) } : void 0;
71
+ return /* @__PURE__ */ jsxs(
72
+ "div",
73
+ {
74
+ "data-graph-group": box.id,
75
+ "data-graph-group-variant": box.record ? "record" : "box",
76
+ ...box.collapsed ? { "data-graph-group-collapsed": "" } : {},
77
+ ...box.window ? { "data-graph-window": box.id } : {},
78
+ className: cn(
79
+ "absolute border border-border",
80
+ box.window ? "pointer-events-auto" : "pointer-events-none",
81
+ box.record || box.collapsed ? "overflow-hidden rounded-md bg-card shadow-sm" : "rounded-xl bg-muted/30",
82
+ !box.record && "border-dashed"
83
+ ),
84
+ style: { left: box.x, top: box.y, width: box.width, height: box.height },
85
+ children: [
86
+ box.record || box.collapsed ? /* @__PURE__ */ jsx(Header, { box, caption, title: group == null ? void 0 : group.title, chevron, aside: group == null ? void 0 : group.aside, select }) : /* @__PURE__ */ jsxs("span", { className: "pointer-events-auto absolute left-2 top-0 flex max-w-[calc(100%-1rem)] -translate-y-1/2 items-center gap-0.5 rounded border border-border bg-background px-1.5 text-[10px] font-medium leading-4 text-muted-foreground", children: [
87
+ chevron,
88
+ /* @__PURE__ */ jsx("span", { title: group == null ? void 0 : group.title, className: "pointer-events-auto min-w-0 truncate", children: caption })
89
+ ] }),
90
+ box.window && /* @__PURE__ */ jsx(WindowFooter, { box, rows: box.window, start: starts[box.id] ?? 0, name, onScroll: (rows) => onScroll(box.id, rows) })
91
+ ]
92
+ },
93
+ box.id
94
+ );
95
+ }) });
96
+ }
97
+ export {
98
+ GraphDiagramGroupBoxes
99
+ };
100
+ //# sourceMappingURL=GraphDiagramGroups.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GraphDiagramGroups.js","sources":["../../src/data/GraphDiagramGroups.tsx"],"sourcesContent":["import type { ReactNode } from \"react\";\nimport { IconButton } from \"../components/IconButton\";\nimport { UiChevronDown, UiChevronRight, UiChevronUp } from \"../icons\";\nimport { cn } from \"../lib/utils\";\nimport type { GraphLayoutGroupBox, GroupMemberWindow } from \"./graph-columns-layout\";\nimport { windowRows, type WindowStarts } from \"./graph-group-window\";\nimport { groupName, type GraphDiagramGroup } from \"./graph-diagram-model\";\n\nexport interface GraphDiagramGroupBoxesProps {\n boxes: GraphLayoutGroupBox[];\n groups: GraphDiagramGroup[] | undefined;\n /** Window starts by box id. */\n starts: WindowStarts;\n onScroll: (boxId: string, rows: number) => void;\n /** Shows a chevron on every group whose `collapsed` is set. */\n onGroupToggle: ((groupId: string) => void) | undefined;\n /** The stand-in node of each collapsed group, by group id: its header selects it. */\n standIns: ReadonlyMap<string, string>;\n selectedId: string | undefined;\n onNodeSelect: ((id: string) => void) | undefined;\n}\n\nfunction Chevron({ group, name, onToggle }: { group: GraphDiagramGroup; name: string; onToggle: () => void }) {\n const collapsed = group.collapsed === true;\n return (\n <IconButton icon={collapsed ? UiChevronRight : UiChevronDown} label={`${collapsed ? \"Expand\" : \"Collapse\"} ${name}`} aria-expanded={!collapsed}\n className=\"pointer-events-auto size-4\" onClick={onToggle} />\n );\n}\n\n/** A record's header, or a collapsed group's whole box: chevron, caption, and what it holds. */\nfunction Header({ box, caption, title, chevron, aside, select }: {\n box: GraphLayoutGroupBox;\n caption: ReactNode;\n title: string | undefined;\n chevron: ReactNode;\n aside: ReactNode;\n select: { name: string; selected: boolean; onSelect: () => void } | undefined;\n}) {\n return (\n <div data-graph-record-header=\"\" title={title} className=\"pointer-events-auto flex items-center gap-1 bg-muted px-1.5 text-[11px] font-semibold\" style={{ height: box.headerHeight }}>\n {chevron}\n {select ? (\n <button type=\"button\" aria-label={`Select ${select.name}`} aria-pressed={select.selected} onClick={select.onSelect}\n className={cn(\"min-w-0 truncate rounded-sm text-left hover:underline focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\", select.selected && \"text-primary\")}>\n {caption}\n </button>\n ) : <span className=\"min-w-0 truncate\">{caption}</span>}\n {aside != null && <span className=\"ml-auto shrink-0 pl-2 text-[10px] font-normal text-muted-foreground\">{aside}</span>}\n </div>\n );\n}\n\n/** \"rows a–b of n\" under a windowed group's rows, with buttons that page it. */\nfunction WindowFooter({ box, rows, start, name, onScroll }: { box: GraphLayoutGroupBox; rows: GroupMemberWindow; start: number; name: string; onScroll: (rows: number) => void }) {\n const { first, last, total } = windowRows(rows, start);\n return (\n <div data-graph-window-footer=\"\" className=\"pointer-events-auto absolute inset-x-0 flex items-center gap-1 px-2 text-[10px] text-muted-foreground\"\n style={{ top: rows.top + rows.height - box.y, height: rows.footerHeight }}>\n <span className=\"min-w-0 flex-1 truncate tabular-nums\">rows {first}–{last} of {total}</span>\n <IconButton icon={UiChevronUp} label={`Scroll ${name} up`} className=\"size-4\" disabled={first === 1} onClick={() => onScroll(-rows.rows)} />\n <IconButton icon={UiChevronDown} label={`Scroll ${name} down`} className=\"size-4\" disabled={last === total} onClick={() => onScroll(rows.rows)} />\n </div>\n );\n}\n\n/**\n * Group rectangles, drawn behind the edges and nodes. A record is captioned by a header, a box on its top\n * border; a collapsed group is its header alone. A box lets the pointer through to the stage, so a click\n * inside it never lands on the box; only its caption, chevron and footer take the pointer. A windowed box\n * takes the wheel too, to scroll its members.\n */\nexport function GraphDiagramGroupBoxes({ boxes, groups, starts, onScroll, onGroupToggle, standIns, selectedId, onNodeSelect }: GraphDiagramGroupBoxesProps) {\n const entries = new Map(groups?.map((group) => [group.id, group]));\n return (\n <>\n {boxes.map((box) => {\n const group = entries.get(box.group);\n const name = groupName(group, box.group);\n const caption = group ? group.label : box.group;\n const chevron = group && group.collapsed !== undefined && onGroupToggle ? <Chevron group={group} name={name} onToggle={() => onGroupToggle(box.group)} /> : null;\n const standIn = box.collapsed ? standIns.get(box.group) : undefined;\n const select = standIn !== undefined && onNodeSelect ? { name, selected: selectedId === standIn, onSelect: () => onNodeSelect(standIn) } : undefined;\n return (\n <div\n key={box.id}\n data-graph-group={box.id}\n data-graph-group-variant={box.record ? \"record\" : \"box\"}\n {...(box.collapsed ? { \"data-graph-group-collapsed\": \"\" } : {})}\n {...(box.window ? { \"data-graph-window\": box.id } : {})}\n className={cn(\n \"absolute border border-border\",\n box.window ? \"pointer-events-auto\" : \"pointer-events-none\",\n box.record || box.collapsed ? \"overflow-hidden rounded-md bg-card shadow-sm\" : \"rounded-xl bg-muted/30\",\n !box.record && \"border-dashed\",\n )}\n style={{ left: box.x, top: box.y, width: box.width, height: box.height }}\n >\n {box.record || box.collapsed ? (\n <Header box={box} caption={caption} title={group?.title} chevron={chevron} aside={group?.aside} select={select} />\n ) : (\n <span className=\"pointer-events-auto absolute left-2 top-0 flex max-w-[calc(100%-1rem)] -translate-y-1/2 items-center gap-0.5 rounded border border-border bg-background px-1.5 text-[10px] font-medium leading-4 text-muted-foreground\">\n {chevron}\n <span title={group?.title} className=\"pointer-events-auto min-w-0 truncate\">{caption}</span>\n </span>\n )}\n {box.window && <WindowFooter box={box} rows={box.window} start={starts[box.id] ?? 0} name={name} onScroll={(rows) => onScroll(box.id, rows)} />}\n </div>\n );\n })}\n </>\n );\n}\n"],"names":[],"mappings":"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"}