@flanksource/clicky-ui 0.2.19 → 0.2.21

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 (423) hide show
  1. package/dist/ai.cjs +26 -0
  2. package/dist/ai.cjs.map +1 -0
  3. package/dist/ai.d.ts +2 -0
  4. package/dist/ai.d.ts.map +1 -0
  5. package/dist/ai.js +26 -0
  6. package/dist/ai.js.map +1 -0
  7. package/dist/chat.cjs +7 -0
  8. package/dist/chat.cjs.map +1 -1
  9. package/dist/chat.js +7 -0
  10. package/dist/chat.js.map +1 -1
  11. package/dist/components/FilterBar.cjs +49 -18
  12. package/dist/components/FilterBar.cjs.map +1 -1
  13. package/dist/components/FilterBar.d.ts +0 -2
  14. package/dist/components/FilterBar.d.ts.map +1 -1
  15. package/dist/components/FilterBar.js +50 -19
  16. package/dist/components/FilterBar.js.map +1 -1
  17. package/dist/components/SearchInput.cjs +63 -0
  18. package/dist/components/SearchInput.cjs.map +1 -0
  19. package/dist/components/SearchInput.d.ts +31 -0
  20. package/dist/components/SearchInput.d.ts.map +1 -0
  21. package/dist/components/SearchInput.js +63 -0
  22. package/dist/components/SearchInput.js.map +1 -0
  23. package/dist/components/SegmentedControl.cjs +88 -0
  24. package/dist/components/SegmentedControl.cjs.map +1 -0
  25. package/dist/components/SegmentedControl.d.ts +38 -0
  26. package/dist/components/SegmentedControl.d.ts.map +1 -0
  27. package/dist/components/SegmentedControl.js +88 -0
  28. package/dist/components/SegmentedControl.js.map +1 -0
  29. package/dist/components/Switch.cjs +51 -0
  30. package/dist/components/Switch.cjs.map +1 -0
  31. package/dist/components/Switch.d.ts +23 -0
  32. package/dist/components/Switch.d.ts.map +1 -0
  33. package/dist/components/Switch.js +51 -0
  34. package/dist/components/Switch.js.map +1 -0
  35. package/dist/components/TimeRange.cjs +53 -45
  36. package/dist/components/TimeRange.cjs.map +1 -1
  37. package/dist/components/TimeRange.d.ts.map +1 -1
  38. package/dist/components/TimeRange.js +53 -45
  39. package/dist/components/TimeRange.js.map +1 -1
  40. package/dist/components/TreePickerField.cjs +5 -1
  41. package/dist/components/TreePickerField.cjs.map +1 -1
  42. package/dist/components/TreePickerField.d.ts.map +1 -1
  43. package/dist/components/TreePickerField.js +5 -1
  44. package/dist/components/TreePickerField.js.map +1 -1
  45. package/dist/components/filter-bar-utils.cjs +5 -0
  46. package/dist/components/filter-bar-utils.cjs.map +1 -1
  47. package/dist/components/filter-bar-utils.d.ts +2 -0
  48. package/dist/components/filter-bar-utils.d.ts.map +1 -1
  49. package/dist/components/filter-bar-utils.js +5 -0
  50. package/dist/components/filter-bar-utils.js.map +1 -1
  51. package/dist/components/json-schema-form-fields.cjs +8 -2
  52. package/dist/components/json-schema-form-fields.cjs.map +1 -1
  53. package/dist/components/json-schema-form-fields.d.ts.map +1 -1
  54. package/dist/components/json-schema-form-fields.js +8 -2
  55. package/dist/components/json-schema-form-fields.js.map +1 -1
  56. package/dist/components/json-schema-form-resolve.cjs +1 -1
  57. package/dist/components/json-schema-form-resolve.cjs.map +1 -1
  58. package/dist/components/json-schema-form-resolve.js +1 -1
  59. package/dist/components/json-schema-form-resolve.js.map +1 -1
  60. package/dist/components.cjs +15 -1
  61. package/dist/components.cjs.map +1 -1
  62. package/dist/components.d.ts +8 -1
  63. package/dist/components.d.ts.map +1 -1
  64. package/dist/components.js +15 -1
  65. package/dist/components.js.map +1 -1
  66. package/dist/data/Clicky.cjs +33 -44
  67. package/dist/data/Clicky.cjs.map +1 -1
  68. package/dist/data/Clicky.d.ts +0 -9
  69. package/dist/data/Clicky.d.ts.map +1 -1
  70. package/dist/data/Clicky.js +31 -42
  71. package/dist/data/Clicky.js.map +1 -1
  72. package/dist/data/DataTable.cjs +73 -50
  73. package/dist/data/DataTable.cjs.map +1 -1
  74. package/dist/data/DataTable.d.ts +4 -0
  75. package/dist/data/DataTable.d.ts.map +1 -1
  76. package/dist/data/DataTable.js +73 -50
  77. package/dist/data/DataTable.js.map +1 -1
  78. package/dist/data/Icon.cjs +2 -5
  79. package/dist/data/Icon.cjs.map +1 -1
  80. package/dist/data/Icon.d.ts +1 -21
  81. package/dist/data/Icon.d.ts.map +1 -1
  82. package/dist/data/Icon.js +3 -6
  83. package/dist/data/Icon.js.map +1 -1
  84. package/dist/data/MatrixTable.cjs +4 -4
  85. package/dist/data/MatrixTable.cjs.map +1 -1
  86. package/dist/data/MatrixTable.js +4 -4
  87. package/dist/data/MatrixTable.js.map +1 -1
  88. package/dist/data/RadialGauge.cjs +76 -0
  89. package/dist/data/RadialGauge.cjs.map +1 -0
  90. package/dist/data/RadialGauge.d.ts +24 -0
  91. package/dist/data/RadialGauge.d.ts.map +1 -0
  92. package/dist/data/RadialGauge.js +76 -0
  93. package/dist/data/RadialGauge.js.map +1 -0
  94. package/dist/data/StatusBreakdown.cjs +0 -4
  95. package/dist/data/StatusBreakdown.cjs.map +1 -1
  96. package/dist/data/StatusBreakdown.d.ts +0 -2
  97. package/dist/data/StatusBreakdown.d.ts.map +1 -1
  98. package/dist/data/StatusBreakdown.js +1 -5
  99. package/dist/data/StatusBreakdown.js.map +1 -1
  100. package/dist/data/Timeline.cjs +61 -0
  101. package/dist/data/Timeline.cjs.map +1 -0
  102. package/dist/data/Timeline.d.ts +36 -0
  103. package/dist/data/Timeline.d.ts.map +1 -0
  104. package/dist/data/Timeline.js +61 -0
  105. package/dist/data/Timeline.js.map +1 -0
  106. package/dist/data/TimeseriesCoreBars.cjs +2 -25
  107. package/dist/data/TimeseriesCoreBars.cjs.map +1 -1
  108. package/dist/data/TimeseriesCoreBars.d.ts +0 -19
  109. package/dist/data/TimeseriesCoreBars.d.ts.map +1 -1
  110. package/dist/data/TimeseriesCoreBars.js +2 -25
  111. package/dist/data/TimeseriesCoreBars.js.map +1 -1
  112. package/dist/data/TimeseriesCoreBars.model.cjs +27 -0
  113. package/dist/data/TimeseriesCoreBars.model.cjs.map +1 -0
  114. package/dist/data/TimeseriesCoreBars.model.d.ts +20 -0
  115. package/dist/data/TimeseriesCoreBars.model.d.ts.map +1 -0
  116. package/dist/data/TimeseriesCoreBars.model.js +27 -0
  117. package/dist/data/TimeseriesCoreBars.model.js.map +1 -0
  118. package/dist/data/TimeseriesPanel.axes.cjs.map +1 -1
  119. package/dist/data/TimeseriesPanel.axes.d.ts +1 -1
  120. package/dist/data/TimeseriesPanel.axes.d.ts.map +1 -1
  121. package/dist/data/TimeseriesPanel.axes.js.map +1 -1
  122. package/dist/data/TimeseriesPanel.cjs +4 -54
  123. package/dist/data/TimeseriesPanel.cjs.map +1 -1
  124. package/dist/data/TimeseriesPanel.d.ts +2 -138
  125. package/dist/data/TimeseriesPanel.d.ts.map +1 -1
  126. package/dist/data/TimeseriesPanel.js +2 -52
  127. package/dist/data/TimeseriesPanel.js.map +1 -1
  128. package/dist/data/TimeseriesPanel.model.cjs +53 -0
  129. package/dist/data/TimeseriesPanel.model.cjs.map +1 -0
  130. package/dist/data/TimeseriesPanel.model.d.ts +88 -0
  131. package/dist/data/TimeseriesPanel.model.d.ts.map +1 -0
  132. package/dist/data/TimeseriesPanel.model.js +53 -0
  133. package/dist/data/TimeseriesPanel.model.js.map +1 -0
  134. package/dist/data/Tree.cjs +1 -1
  135. package/dist/data/Tree.cjs.map +1 -1
  136. package/dist/data/Tree.js +1 -1
  137. package/dist/data/Tree.js.map +1 -1
  138. package/dist/data/ai/ChatFab.cjs +29 -0
  139. package/dist/data/ai/ChatFab.cjs.map +1 -0
  140. package/dist/data/ai/ChatFab.d.ts +12 -0
  141. package/dist/data/ai/ChatFab.d.ts.map +1 -0
  142. package/dist/data/ai/ChatFab.js +29 -0
  143. package/dist/data/ai/ChatFab.js.map +1 -0
  144. package/dist/data/ai/ChatWindow.cjs +178 -0
  145. package/dist/data/ai/ChatWindow.cjs.map +1 -0
  146. package/dist/data/ai/ChatWindow.d.ts +38 -0
  147. package/dist/data/ai/ChatWindow.d.ts.map +1 -0
  148. package/dist/data/ai/ChatWindow.js +156 -0
  149. package/dist/data/ai/ChatWindow.js.map +1 -0
  150. package/dist/data/ai/ChatWindowManager.cjs +139 -0
  151. package/dist/data/ai/ChatWindowManager.cjs.map +1 -0
  152. package/dist/data/ai/ChatWindowManager.d.ts +12 -0
  153. package/dist/data/ai/ChatWindowManager.d.ts.map +1 -0
  154. package/dist/data/ai/ChatWindowManager.js +139 -0
  155. package/dist/data/ai/ChatWindowManager.js.map +1 -0
  156. package/dist/data/ai/ContextBadges.cjs +74 -0
  157. package/dist/data/ai/ContextBadges.cjs.map +1 -0
  158. package/dist/data/ai/ContextBadges.d.ts +16 -0
  159. package/dist/data/ai/ContextBadges.d.ts.map +1 -0
  160. package/dist/data/ai/ContextBadges.js +74 -0
  161. package/dist/data/ai/ContextBadges.js.map +1 -0
  162. package/dist/data/ai/ThreadPicker.cjs +148 -0
  163. package/dist/data/ai/ThreadPicker.cjs.map +1 -0
  164. package/dist/data/ai/ThreadPicker.d.ts +37 -0
  165. package/dist/data/ai/ThreadPicker.d.ts.map +1 -0
  166. package/dist/data/ai/ThreadPicker.js +148 -0
  167. package/dist/data/ai/ThreadPicker.js.map +1 -0
  168. package/dist/data/ai/ToolPreferences.cjs +80 -0
  169. package/dist/data/ai/ToolPreferences.cjs.map +1 -0
  170. package/dist/data/ai/ToolPreferences.d.ts +19 -0
  171. package/dist/data/ai/ToolPreferences.d.ts.map +1 -0
  172. package/dist/data/ai/ToolPreferences.js +80 -0
  173. package/dist/data/ai/ToolPreferences.js.map +1 -0
  174. package/dist/data/ai/chat-window-context.cjs +78 -0
  175. package/dist/data/ai/chat-window-context.cjs.map +1 -0
  176. package/dist/data/ai/chat-window-context.d.ts +57 -0
  177. package/dist/data/ai/chat-window-context.d.ts.map +1 -0
  178. package/dist/data/ai/chat-window-context.js +78 -0
  179. package/dist/data/ai/chat-window-context.js.map +1 -0
  180. package/dist/data/ai/context.cjs +43 -0
  181. package/dist/data/ai/context.cjs.map +1 -0
  182. package/dist/data/ai/context.d.ts +35 -0
  183. package/dist/data/ai/context.d.ts.map +1 -0
  184. package/dist/data/ai/context.js +43 -0
  185. package/dist/data/ai/context.js.map +1 -0
  186. package/dist/data/ai/index.d.ts +10 -0
  187. package/dist/data/ai/index.d.ts.map +1 -0
  188. package/dist/data/cache-browser/CacheDetailPanel.cjs +15 -0
  189. package/dist/data/cache-browser/CacheDetailPanel.cjs.map +1 -1
  190. package/dist/data/cache-browser/CacheDetailPanel.d.ts.map +1 -1
  191. package/dist/data/cache-browser/CacheDetailPanel.js +15 -0
  192. package/dist/data/cache-browser/CacheDetailPanel.js.map +1 -1
  193. package/dist/data/cache-browser/cache-browser.fixtures.d.ts +10 -0
  194. package/dist/data/cache-browser/cache-browser.fixtures.d.ts.map +1 -0
  195. package/dist/data/cache-browser/download.cjs +13 -0
  196. package/dist/data/cache-browser/download.cjs.map +1 -0
  197. package/dist/data/cache-browser/download.d.ts +3 -0
  198. package/dist/data/cache-browser/download.d.ts.map +1 -0
  199. package/dist/data/cache-browser/download.js +13 -0
  200. package/dist/data/cache-browser/download.js.map +1 -0
  201. package/dist/data/chat/Chat.cjs +44 -3
  202. package/dist/data/chat/Chat.cjs.map +1 -1
  203. package/dist/data/chat/Chat.d.ts +5 -2
  204. package/dist/data/chat/Chat.d.ts.map +1 -1
  205. package/dist/data/chat/Chat.fixtures.cjs +86 -0
  206. package/dist/data/chat/Chat.fixtures.cjs.map +1 -0
  207. package/dist/data/chat/Chat.fixtures.d.ts +4 -0
  208. package/dist/data/chat/Chat.fixtures.d.ts.map +1 -1
  209. package/dist/data/chat/Chat.fixtures.js +86 -0
  210. package/dist/data/chat/Chat.fixtures.js.map +1 -0
  211. package/dist/data/chat/Chat.js +45 -4
  212. package/dist/data/chat/Chat.js.map +1 -1
  213. package/dist/data/chat/ContextUsage.cjs +99 -0
  214. package/dist/data/chat/ContextUsage.cjs.map +1 -0
  215. package/dist/data/chat/ContextUsage.d.ts +19 -0
  216. package/dist/data/chat/ContextUsage.d.ts.map +1 -0
  217. package/dist/data/chat/ContextUsage.js +99 -0
  218. package/dist/data/chat/ContextUsage.js.map +1 -0
  219. package/dist/data/chat/Conversation.cjs +47 -2
  220. package/dist/data/chat/Conversation.cjs.map +1 -1
  221. package/dist/data/chat/Conversation.d.ts +8 -2
  222. package/dist/data/chat/Conversation.d.ts.map +1 -1
  223. package/dist/data/chat/Conversation.js +47 -2
  224. package/dist/data/chat/Conversation.js.map +1 -1
  225. package/dist/data/chat/ModelSelector.cjs +28 -14
  226. package/dist/data/chat/ModelSelector.cjs.map +1 -1
  227. package/dist/data/chat/ModelSelector.d.ts +5 -4
  228. package/dist/data/chat/ModelSelector.d.ts.map +1 -1
  229. package/dist/data/chat/ModelSelector.js +28 -14
  230. package/dist/data/chat/ModelSelector.js.map +1 -1
  231. package/dist/data/chat/clickyOperationsToTools.cjs +21 -1
  232. package/dist/data/chat/clickyOperationsToTools.cjs.map +1 -1
  233. package/dist/data/chat/clickyOperationsToTools.d.ts +5 -4
  234. package/dist/data/chat/clickyOperationsToTools.d.ts.map +1 -1
  235. package/dist/data/chat/clickyOperationsToTools.js +21 -1
  236. package/dist/data/chat/clickyOperationsToTools.js.map +1 -1
  237. package/dist/data/chat/index.d.ts +4 -1
  238. package/dist/data/chat/index.d.ts.map +1 -1
  239. package/dist/data/chat/provider-icons.cjs +15 -0
  240. package/dist/data/chat/provider-icons.cjs.map +1 -0
  241. package/dist/data/chat/provider-icons.d.ts +7 -0
  242. package/dist/data/chat/provider-icons.d.ts.map +1 -0
  243. package/dist/data/chat/provider-icons.js +15 -0
  244. package/dist/data/chat/provider-icons.js.map +1 -0
  245. package/dist/data/chat/types.cjs.map +1 -1
  246. package/dist/data/chat/types.d.ts +41 -9
  247. package/dist/data/chat/types.d.ts.map +1 -1
  248. package/dist/data/chat/types.js.map +1 -1
  249. package/dist/data/clicky-parse.cjs +42 -0
  250. package/dist/data/clicky-parse.cjs.map +1 -0
  251. package/dist/data/clicky-parse.d.ts +11 -0
  252. package/dist/data/clicky-parse.d.ts.map +1 -0
  253. package/dist/data/clicky-parse.js +42 -0
  254. package/dist/data/clicky-parse.js.map +1 -0
  255. package/dist/data/diagnostics/FrameSourceWindow.cjs +0 -4
  256. package/dist/data/diagnostics/FrameSourceWindow.cjs.map +1 -1
  257. package/dist/data/diagnostics/FrameSourceWindow.d.ts +1 -11
  258. package/dist/data/diagnostics/FrameSourceWindow.d.ts.map +1 -1
  259. package/dist/data/diagnostics/FrameSourceWindow.js +1 -5
  260. package/dist/data/diagnostics/FrameSourceWindow.js.map +1 -1
  261. package/dist/data/diagnostics/FrameSourceWindow.utils.cjs +7 -0
  262. package/dist/data/diagnostics/FrameSourceWindow.utils.cjs.map +1 -0
  263. package/dist/data/diagnostics/FrameSourceWindow.utils.d.ts +12 -0
  264. package/dist/data/diagnostics/FrameSourceWindow.utils.d.ts.map +1 -0
  265. package/dist/data/diagnostics/FrameSourceWindow.utils.js +7 -0
  266. package/dist/data/diagnostics/FrameSourceWindow.utils.js.map +1 -0
  267. package/dist/data/diagnostics/JvmStackTrace.cjs +2 -1
  268. package/dist/data/diagnostics/JvmStackTrace.cjs.map +1 -1
  269. package/dist/data/diagnostics/JvmStackTrace.d.ts.map +1 -1
  270. package/dist/data/diagnostics/JvmStackTrace.js +2 -1
  271. package/dist/data/diagnostics/JvmStackTrace.js.map +1 -1
  272. package/dist/data/icon-fallback.cjs +12 -0
  273. package/dist/data/icon-fallback.cjs.map +1 -0
  274. package/dist/data/icon-fallback.d.ts +19 -0
  275. package/dist/data/icon-fallback.d.ts.map +1 -0
  276. package/dist/data/icon-fallback.js +12 -0
  277. package/dist/data/icon-fallback.js.map +1 -0
  278. package/dist/data/status-breakdown-utils.cjs +7 -0
  279. package/dist/data/status-breakdown-utils.cjs.map +1 -0
  280. package/dist/data/status-breakdown-utils.d.ts +4 -0
  281. package/dist/data/status-breakdown-utils.d.ts.map +1 -0
  282. package/dist/data/status-breakdown-utils.js +7 -0
  283. package/dist/data/status-breakdown-utils.js.map +1 -0
  284. package/dist/data/test-runner/TestRunSummary.cjs +36 -0
  285. package/dist/data/test-runner/TestRunSummary.cjs.map +1 -1
  286. package/dist/data/test-runner/TestRunSummary.d.ts +7 -1
  287. package/dist/data/test-runner/TestRunSummary.d.ts.map +1 -1
  288. package/dist/data/test-runner/TestRunSummary.js +36 -0
  289. package/dist/data/test-runner/TestRunSummary.js.map +1 -1
  290. package/dist/data/test-runner/TestRunner.cjs +5 -3
  291. package/dist/data/test-runner/TestRunner.cjs.map +1 -1
  292. package/dist/data/test-runner/TestRunner.d.ts +13 -1
  293. package/dist/data/test-runner/TestRunner.d.ts.map +1 -1
  294. package/dist/data/test-runner/TestRunner.js +5 -3
  295. package/dist/data/test-runner/TestRunner.js.map +1 -1
  296. package/dist/data/version-info.cjs +3 -3
  297. package/dist/data/version-info.js +3 -3
  298. package/dist/data.cjs +19 -6
  299. package/dist/data.cjs.map +1 -1
  300. package/dist/data.d.ts +13 -5
  301. package/dist/data.d.ts.map +1 -1
  302. package/dist/data.js +18 -5
  303. package/dist/data.js.map +1 -1
  304. package/dist/index.cjs +51 -7
  305. package/dist/index.cjs.map +1 -1
  306. package/dist/index.js +50 -6
  307. package/dist/index.js.map +1 -1
  308. package/dist/layout/AppShell.cjs +179 -29
  309. package/dist/layout/AppShell.cjs.map +1 -1
  310. package/dist/layout/AppShell.d.ts +5 -5
  311. package/dist/layout/AppShell.d.ts.map +1 -1
  312. package/dist/layout/AppShell.js +179 -29
  313. package/dist/layout/AppShell.js.map +1 -1
  314. package/dist/layout/AppSidebar.cjs +239 -0
  315. package/dist/layout/AppSidebar.cjs.map +1 -0
  316. package/dist/layout/AppSidebar.d.ts +62 -0
  317. package/dist/layout/AppSidebar.d.ts.map +1 -0
  318. package/dist/layout/AppSidebar.js +239 -0
  319. package/dist/layout/AppSidebar.js.map +1 -0
  320. package/dist/overlay/DropdownMenu.cjs.map +1 -1
  321. package/dist/overlay/DropdownMenu.d.ts.map +1 -1
  322. package/dist/overlay/DropdownMenu.js.map +1 -1
  323. package/dist/overlay/Modal.cjs +4 -2
  324. package/dist/overlay/Modal.cjs.map +1 -1
  325. package/dist/overlay/Modal.d.ts +1 -1
  326. package/dist/overlay/Modal.d.ts.map +1 -1
  327. package/dist/overlay/Modal.js +4 -2
  328. package/dist/overlay/Modal.js.map +1 -1
  329. package/dist/overlay/Toast.cjs +89 -0
  330. package/dist/overlay/Toast.cjs.map +1 -0
  331. package/dist/overlay/Toast.d.ts +14 -0
  332. package/dist/overlay/Toast.d.ts.map +1 -0
  333. package/dist/overlay/Toast.js +89 -0
  334. package/dist/overlay/Toast.js.map +1 -0
  335. package/dist/overlay/toast-context.cjs +12 -0
  336. package/dist/overlay/toast-context.cjs.map +1 -0
  337. package/dist/overlay/toast-context.d.ts +24 -0
  338. package/dist/overlay/toast-context.d.ts.map +1 -0
  339. package/dist/overlay/toast-context.js +12 -0
  340. package/dist/overlay/toast-context.js.map +1 -0
  341. package/dist/rpc/AcceptPicker.cjs +81 -58
  342. package/dist/rpc/AcceptPicker.cjs.map +1 -1
  343. package/dist/rpc/AcceptPicker.d.ts.map +1 -1
  344. package/dist/rpc/AcceptPicker.js +81 -58
  345. package/dist/rpc/AcceptPicker.js.map +1 -1
  346. package/dist/rpc/CommandForm.cjs +5 -35
  347. package/dist/rpc/CommandForm.cjs.map +1 -1
  348. package/dist/rpc/CommandForm.d.ts +0 -3
  349. package/dist/rpc/CommandForm.d.ts.map +1 -1
  350. package/dist/rpc/CommandForm.js +2 -32
  351. package/dist/rpc/CommandForm.js.map +1 -1
  352. package/dist/rpc/CommandOutput.cjs +2 -1
  353. package/dist/rpc/CommandOutput.cjs.map +1 -1
  354. package/dist/rpc/CommandOutput.d.ts.map +1 -1
  355. package/dist/rpc/CommandOutput.js +2 -1
  356. package/dist/rpc/CommandOutput.js.map +1 -1
  357. package/dist/rpc/EntityExplorerApp.cjs +28 -83
  358. package/dist/rpc/EntityExplorerApp.cjs.map +1 -1
  359. package/dist/rpc/EntityExplorerApp.d.ts +1 -4
  360. package/dist/rpc/EntityExplorerApp.d.ts.map +1 -1
  361. package/dist/rpc/EntityExplorerApp.js +13 -68
  362. package/dist/rpc/EntityExplorerApp.js.map +1 -1
  363. package/dist/rpc/OperationCatalog.cjs +2 -2
  364. package/dist/rpc/OperationCatalog.cjs.map +1 -1
  365. package/dist/rpc/OperationCatalog.d.ts +1 -1
  366. package/dist/rpc/OperationCatalog.d.ts.map +1 -1
  367. package/dist/rpc/OperationCatalog.js +1 -1
  368. package/dist/rpc/OperationCatalog.js.map +1 -1
  369. package/dist/rpc/OperationCommandPage.cjs +6 -4
  370. package/dist/rpc/OperationCommandPage.cjs.map +1 -1
  371. package/dist/rpc/OperationCommandPage.d.ts.map +1 -1
  372. package/dist/rpc/OperationCommandPage.js +3 -1
  373. package/dist/rpc/OperationCommandPage.js.map +1 -1
  374. package/dist/rpc/RouterProvider.cjs +10 -0
  375. package/dist/rpc/RouterProvider.cjs.map +1 -0
  376. package/dist/rpc/RouterProvider.d.ts +10 -0
  377. package/dist/rpc/RouterProvider.d.ts.map +1 -0
  378. package/dist/rpc/RouterProvider.js +10 -0
  379. package/dist/rpc/RouterProvider.js.map +1 -0
  380. package/dist/rpc/apiClient.cjs +4 -4
  381. package/dist/rpc/apiClient.cjs.map +1 -1
  382. package/dist/rpc/apiClient.js +4 -4
  383. package/dist/rpc/apiClient.js.map +1 -1
  384. package/dist/rpc/command-form-utils.cjs +43 -0
  385. package/dist/rpc/command-form-utils.cjs.map +1 -0
  386. package/dist/rpc/command-form-utils.d.ts +5 -0
  387. package/dist/rpc/command-form-utils.d.ts.map +1 -0
  388. package/dist/rpc/command-form-utils.js +43 -0
  389. package/dist/rpc/command-form-utils.js.map +1 -0
  390. package/dist/rpc/commandHref.cjs +62 -0
  391. package/dist/rpc/commandHref.cjs.map +1 -0
  392. package/dist/rpc/commandHref.d.ts +7 -0
  393. package/dist/rpc/commandHref.d.ts.map +1 -0
  394. package/dist/rpc/commandHref.js +62 -0
  395. package/dist/rpc/commandHref.js.map +1 -0
  396. package/dist/rpc/formMetadata.cjs +1 -1
  397. package/dist/rpc/formMetadata.cjs.map +1 -1
  398. package/dist/rpc/formMetadata.js +1 -1
  399. package/dist/rpc/formMetadata.js.map +1 -1
  400. package/dist/rpc/router.cjs +83 -0
  401. package/dist/rpc/router.cjs.map +1 -0
  402. package/dist/rpc/router.d.ts +24 -0
  403. package/dist/rpc/router.d.ts.map +1 -0
  404. package/dist/rpc/router.js +83 -0
  405. package/dist/rpc/router.js.map +1 -0
  406. package/dist/rpc/rpc-story-fixtures/orders.fixture.d.ts +3 -0
  407. package/dist/rpc/rpc-story-fixtures/orders.fixture.d.ts.map +1 -0
  408. package/dist/rpc/rpc-story-fixtures/services.fixture.d.ts +3 -0
  409. package/dist/rpc/rpc-story-fixtures/services.fixture.d.ts.map +1 -0
  410. package/dist/rpc/rpc-story-fixtures/surface-fixture.d.ts +24 -0
  411. package/dist/rpc/rpc-story-fixtures/surface-fixture.d.ts.map +1 -0
  412. package/dist/rpc/rpc-story-fixtures/widgets.fixture.d.ts +3 -0
  413. package/dist/rpc/rpc-story-fixtures/widgets.fixture.d.ts.map +1 -0
  414. package/dist/rpc/rpc-story.fixtures.d.ts +16 -0
  415. package/dist/rpc/rpc-story.fixtures.d.ts.map +1 -0
  416. package/dist/rpc.cjs +17 -0
  417. package/dist/rpc.cjs.map +1 -1
  418. package/dist/rpc.d.ts +5 -0
  419. package/dist/rpc.d.ts.map +1 -1
  420. package/dist/rpc.js +18 -1
  421. package/dist/rpc.js.map +1 -1
  422. package/dist/styles.css +1 -1
  423. package/package.json +11 -1
@@ -50,5 +50,5 @@ export type ModalProps = {
50
50
  /** Modal body content. */
51
51
  children: ReactNode;
52
52
  };
53
- export declare function Modal({ open, onClose, confirmClose, title, subtitle, size, closeOnBackdrop, closeOnEsc, hideClose, expandable, className, headerSlot, footer, children, }: ModalProps): import("react/jsx-runtime").JSX.Element | null;
53
+ export declare function Modal({ open, onClose, confirmClose, title, subtitle, size, closeOnBackdrop, closeOnEsc, hideClose, expandable, className, headerSlot, footer, children, }: ModalProps): import('react').ReactPortal | null;
54
54
  //# sourceMappingURL=Modal.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Modal.d.ts","sourceRoot":"","sources":["../../src/overlay/Modal.tsx"],"names":[],"mappings":"AAAA,OAAO,EAA+B,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAOpE,MAAM,MAAM,SAAS,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,MAAM,CAAC;AAE3D,6EAA6E;AAC7E,MAAM,MAAM,mBAAmB,GAAG;IAChC,0CAA0C;IAC1C,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,6CAA6C;IAC7C,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB,sDAAsD;IACtD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,8EAA8E;IAC9E,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG;IACvB,6CAA6C;IAC7C,IAAI,EAAE,OAAO,CAAC;IACd,+CAA+C;IAC/C,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB;;;;;OAKG;IACH,YAAY,CAAC,EAAE,OAAO,GAAG,mBAAmB,CAAC;IAC7C,oEAAoE;IACpE,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,0CAA0C;IAC1C,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,gGAAgG;IAChG,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,oCAAoC;IACpC,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,6BAA6B;IAC7B,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,qCAAqC;IACrC,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,2CAA2C;IAC3C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,qEAAqE;IACrE,UAAU,CAAC,EAAE,SAAS,CAAC;IACvB,uDAAuD;IACvD,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,0BAA0B;IAC1B,QAAQ,EAAE,SAAS,CAAC;CACrB,CAAC;AAiBF,wBAAgB,KAAK,CAAC,EACpB,IAAI,EACJ,OAAO,EACP,YAAoB,EACpB,KAAK,EACL,QAAQ,EACR,IAAW,EACX,eAAuB,EACvB,UAAiB,EACjB,SAAiB,EACjB,UAAiB,EACjB,SAAS,EACT,UAAU,EACV,MAAM,EACN,QAAQ,GACT,EAAE,UAAU,kDA2HZ"}
1
+ {"version":3,"file":"Modal.d.ts","sourceRoot":"","sources":["../../src/overlay/Modal.tsx"],"names":[],"mappings":"AAAA,OAAO,EAA+B,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAQpE,MAAM,MAAM,SAAS,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,MAAM,CAAC;AAE3D,6EAA6E;AAC7E,MAAM,MAAM,mBAAmB,GAAG;IAChC,0CAA0C;IAC1C,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,6CAA6C;IAC7C,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB,sDAAsD;IACtD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,8EAA8E;IAC9E,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG;IACvB,6CAA6C;IAC7C,IAAI,EAAE,OAAO,CAAC;IACd,+CAA+C;IAC/C,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB;;;;;OAKG;IACH,YAAY,CAAC,EAAE,OAAO,GAAG,mBAAmB,CAAC;IAC7C,oEAAoE;IACpE,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,0CAA0C;IAC1C,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,gGAAgG;IAChG,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,oCAAoC;IACpC,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,6BAA6B;IAC7B,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,qCAAqC;IACrC,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,2CAA2C;IAC3C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,qEAAqE;IACrE,UAAU,CAAC,EAAE,SAAS,CAAC;IACvB,uDAAuD;IACvD,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,0BAA0B;IAC1B,QAAQ,EAAE,SAAS,CAAC;CACrB,CAAC;AAiBF,wBAAgB,KAAK,CAAC,EACpB,IAAI,EACJ,OAAO,EACP,YAAoB,EACpB,KAAK,EACL,QAAQ,EACR,IAAW,EACX,eAAuB,EACvB,UAAiB,EACjB,SAAiB,EACjB,UAAiB,EACjB,SAAS,EACT,UAAU,EACV,MAAM,EACN,QAAQ,GACT,EAAE,UAAU,sCAoIZ"}
@@ -1,5 +1,6 @@
1
1
  import { jsx, jsxs } from "react/jsx-runtime";
2
2
  import { useRef, useState, useEffect } from "react";
3
+ import { createPortal } from "react-dom";
3
4
  import { cn } from "../lib/utils.js";
4
5
  import { Icon } from "../data/Icon.js";
5
6
  import { Button } from "../components/button.js";
@@ -73,7 +74,7 @@ function Modal({
73
74
  };
74
75
  }, [open]);
75
76
  if (!open) return null;
76
- return /* @__PURE__ */ jsx(
77
+ const overlay = /* @__PURE__ */ jsx(
77
78
  "div",
78
79
  {
79
80
  className: cn(
@@ -81,7 +82,7 @@ function Modal({
81
82
  // Nested modals dim less so the dialog they opened over stays visible.
82
83
  depth === 0 ? "bg-black/40" : "bg-black/20"
83
84
  ),
84
- style: { zIndex: 50 + depth * 10 },
85
+ style: { zIndex: 1e4 + depth * 10 },
85
86
  onClick: closeOnBackdrop ? requestClose : void 0,
86
87
  role: "presentation",
87
88
  children: /* @__PURE__ */ jsxs(
@@ -144,6 +145,7 @@ function Modal({
144
145
  )
145
146
  }
146
147
  );
148
+ return typeof document !== "undefined" ? createPortal(overlay, document.body) : null;
147
149
  }
148
150
  function ConfirmClosePrompt({
149
151
  options,
@@ -1 +1 @@
1
- {"version":3,"file":"Modal.js","sources":["../../src/overlay/Modal.tsx"],"sourcesContent":["import { useEffect, useRef, useState, type ReactNode } from \"react\";\nimport { cn } from \"../lib/utils\";\nimport { Icon } from \"../data/Icon\";\nimport { Button } from \"../components/button\";\nimport { UiClose, UiFullscreen, UiFullscreenFilled } from \"../icons\";\nimport { useModalStack } from \"./modalStack\";\n\nexport type ModalSize = \"sm\" | \"md\" | \"lg\" | \"xl\" | \"full\";\n\n/** Copy for the discard-confirmation prompt shown before a guarded close. */\nexport type ConfirmCloseOptions = {\n /** Heading of the confirmation prompt. */\n title?: ReactNode;\n /** Body explaining what is lost on close. */\n message?: ReactNode;\n /** Label of the button that proceeds with closing. */\n confirmLabel?: string;\n /** Label of the button that dismisses the prompt and keeps the modal open. */\n cancelLabel?: string;\n};\n\nexport type ModalProps = {\n /** Controls whether the modal is mounted. */\n open: boolean;\n /** Called when the modal requests to close. */\n onClose: () => void;\n /**\n * Guard every close path (close button, Escape, backdrop) behind a discard\n * confirmation. `true` uses the default copy; pass options to customise it.\n * `onClose` only fires once the user confirms. Set this while the modal holds\n * unsaved edits and clear it (or pass `false`) once there is nothing to lose.\n */\n confirmClose?: boolean | ConfirmCloseOptions;\n /** Header title and accessible dialog label when it is a string. */\n title?: ReactNode;\n /**\n * Secondary header content rendered on its own row directly beneath the title.\n * The title stays a single row alongside the expand/close buttons, so a tall\n * subtitle (e.g. a tab switcher) never pushes those buttons down.\n */\n subtitle?: ReactNode;\n /** Width/height preset for the dialog. */\n size?: ModalSize;\n /** Close when the backdrop is clicked. Off by default; close via Escape or the close button. */\n closeOnBackdrop?: boolean;\n /** Close when Escape is pressed. */\n closeOnEsc?: boolean;\n /** Hide the close button. */\n hideClose?: boolean;\n /** Show an expand/restore button. */\n expandable?: boolean;\n /** Classes applied to the dialog panel. */\n className?: string;\n /** Extra header content rendered before the expand/close buttons. */\n headerSlot?: ReactNode;\n /** Footer content pinned below the scrollable body. */\n footer?: ReactNode;\n /** Modal body content. */\n children: ReactNode;\n};\n\nconst sizeClass: Record<ModalSize, string> = {\n sm: \"max-w-sm max-h-[90vh]\",\n md: \"max-w-md max-h-[90vh]\",\n lg: \"max-w-2xl max-h-[90vh]\",\n xl: \"max-w-4xl max-h-[90vh]\",\n full: \"max-w-[95vw] max-h-[95vh]\",\n};\n\nconst DEFAULT_CONFIRM: Required<ConfirmCloseOptions> = {\n title: \"Discard changes?\",\n message: \"You have unsaved changes. Closing now will discard them.\",\n confirmLabel: \"Discard\",\n cancelLabel: \"Keep editing\",\n};\n\nexport function Modal({\n open,\n onClose,\n confirmClose = false,\n title,\n subtitle,\n size = \"md\",\n closeOnBackdrop = false,\n closeOnEsc = true,\n hideClose = false,\n expandable = true,\n className,\n headerSlot,\n footer,\n children,\n}: ModalProps) {\n const dialogRef = useRef<HTMLDivElement>(null);\n const { isTop, depth } = useModalStack(open);\n const [expanded, setExpanded] = useState(false);\n // When confirmClose is active, a close request opens this prompt instead of\n // closing outright; onClose only fires once the user confirms the discard.\n const [confirming, setConfirming] = useState(false);\n\n // requestClose is the single entry point for every close affordance. With the\n // guard on, it surfaces the confirmation; otherwise it closes immediately.\n const requestClose = () => {\n if (confirmClose) setConfirming(true);\n else onClose();\n };\n\n useEffect(() => {\n if (!open) {\n setExpanded(false);\n setConfirming(false);\n }\n }, [open]);\n\n // A close guard that disappears mid-prompt (changes saved/reverted) should\n // not leave a stale confirmation dialog up.\n useEffect(() => {\n if (!confirmClose) setConfirming(false);\n }, [confirmClose]);\n\n useEffect(() => {\n // Only the topmost modal handles Escape so a keypress closes one nested\n // layer at a time instead of every open modal at once.\n if (!open || !closeOnEsc || !isTop) return;\n const onKey = (e: KeyboardEvent) => {\n if (e.key !== \"Escape\") return;\n // While the prompt is up, Escape dismisses the prompt rather than the modal.\n if (confirming) setConfirming(false);\n else requestClose();\n };\n document.addEventListener(\"keydown\", onKey);\n return () => document.removeEventListener(\"keydown\", onKey);\n }, [open, closeOnEsc, isTop, confirming, confirmClose, onClose]);\n\n useEffect(() => {\n if (!open) return;\n const prev = document.activeElement as HTMLElement | null;\n dialogRef.current?.focus();\n return () => prev?.focus?.();\n }, [open]);\n\n if (!open) return null;\n\n return (\n <div\n className={cn(\n \"fixed inset-0 flex items-center justify-center\",\n // Nested modals dim less so the dialog they opened over stays visible.\n depth === 0 ? \"bg-black/40\" : \"bg-black/20\",\n )}\n style={{ zIndex: 50 + depth * 10 }}\n onClick={closeOnBackdrop ? requestClose : undefined}\n role=\"presentation\"\n >\n <div\n ref={dialogRef}\n tabIndex={-1}\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label={typeof title === \"string\" ? title : undefined}\n className={cn(\n \"relative bg-background border border-border rounded-lg shadow-xl w-full flex flex-col\",\n expanded ? sizeClass.full : sizeClass[size],\n className,\n )}\n onClick={(e) => e.stopPropagation()}\n >\n {(title || subtitle || headerSlot || expandable || !hideClose) && (\n <div className=\"px-density-4 py-density-3 border-b border-border\">\n <div className=\"flex items-center gap-density-2\">\n {title ? (\n <h2 className=\"text-sm font-semibold flex-1\">{title}</h2>\n ) : (\n <span className=\"flex-1\" />\n )}\n {headerSlot}\n {expandable && (\n <button\n type=\"button\"\n onClick={() => setExpanded((v) => !v)}\n aria-label={expanded ? \"Restore size\" : \"Expand to fullscreen\"}\n className=\"text-muted-foreground hover:text-foreground\"\n >\n <Icon icon={expanded ? UiFullscreenFilled : UiFullscreen} />\n </button>\n )}\n {!hideClose && (\n <button\n type=\"button\"\n onClick={requestClose}\n aria-label=\"Close\"\n className=\"text-muted-foreground hover:text-foreground\"\n >\n <Icon icon={UiClose} />\n </button>\n )}\n </div>\n {subtitle ? <div className=\"mt-density-2\">{subtitle}</div> : null}\n </div>\n )}\n <div className=\"flex-1 overflow-auto px-density-4 py-density-3\">{children}</div>\n {footer && <div className=\"px-density-4 py-density-3 border-t border-border\">{footer}</div>}\n {confirming && (\n <ConfirmClosePrompt\n options={confirmClose === true ? DEFAULT_CONFIRM : { ...DEFAULT_CONFIRM, ...confirmClose }}\n onConfirm={() => {\n setConfirming(false);\n onClose();\n }}\n onCancel={() => setConfirming(false)}\n />\n )}\n </div>\n </div>\n );\n}\n\nfunction ConfirmClosePrompt({\n options,\n onConfirm,\n onCancel,\n}: {\n options: Required<ConfirmCloseOptions>;\n onConfirm: () => void;\n onCancel: () => void;\n}) {\n return (\n <div\n className=\"absolute inset-0 z-10 flex items-center justify-center rounded-lg bg-background/80 p-density-4\"\n role=\"alertdialog\"\n aria-modal=\"true\"\n aria-label={typeof options.title === \"string\" ? options.title : \"Confirm close\"}\n onClick={(e) => e.stopPropagation()}\n >\n <div className=\"w-full max-w-sm rounded-lg border border-border bg-background p-density-4 shadow-xl\">\n <h3 className=\"text-sm font-semibold\">{options.title}</h3>\n <p className=\"mt-density-2 text-sm text-muted-foreground\">{options.message}</p>\n <div className=\"mt-density-4 flex justify-end gap-density-2\">\n <Button variant=\"ghost\" size=\"sm\" onClick={onCancel}>\n {options.cancelLabel}\n </Button>\n <Button variant=\"destructive\" size=\"sm\" onClick={onConfirm}>\n {options.confirmLabel}\n </Button>\n </div>\n </div>\n </div>\n );\n}\n"],"names":["_a"],"mappings":"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"}
1
+ {"version":3,"file":"Modal.js","sources":["../../src/overlay/Modal.tsx"],"sourcesContent":["import { useEffect, useRef, useState, type ReactNode } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { cn } from \"../lib/utils\";\nimport { Icon } from \"../data/Icon\";\nimport { Button } from \"../components/button\";\nimport { UiClose, UiFullscreen, UiFullscreenFilled } from \"../icons\";\nimport { useModalStack } from \"./modalStack\";\n\nexport type ModalSize = \"sm\" | \"md\" | \"lg\" | \"xl\" | \"full\";\n\n/** Copy for the discard-confirmation prompt shown before a guarded close. */\nexport type ConfirmCloseOptions = {\n /** Heading of the confirmation prompt. */\n title?: ReactNode;\n /** Body explaining what is lost on close. */\n message?: ReactNode;\n /** Label of the button that proceeds with closing. */\n confirmLabel?: string;\n /** Label of the button that dismisses the prompt and keeps the modal open. */\n cancelLabel?: string;\n};\n\nexport type ModalProps = {\n /** Controls whether the modal is mounted. */\n open: boolean;\n /** Called when the modal requests to close. */\n onClose: () => void;\n /**\n * Guard every close path (close button, Escape, backdrop) behind a discard\n * confirmation. `true` uses the default copy; pass options to customise it.\n * `onClose` only fires once the user confirms. Set this while the modal holds\n * unsaved edits and clear it (or pass `false`) once there is nothing to lose.\n */\n confirmClose?: boolean | ConfirmCloseOptions;\n /** Header title and accessible dialog label when it is a string. */\n title?: ReactNode;\n /**\n * Secondary header content rendered on its own row directly beneath the title.\n * The title stays a single row alongside the expand/close buttons, so a tall\n * subtitle (e.g. a tab switcher) never pushes those buttons down.\n */\n subtitle?: ReactNode;\n /** Width/height preset for the dialog. */\n size?: ModalSize;\n /** Close when the backdrop is clicked. Off by default; close via Escape or the close button. */\n closeOnBackdrop?: boolean;\n /** Close when Escape is pressed. */\n closeOnEsc?: boolean;\n /** Hide the close button. */\n hideClose?: boolean;\n /** Show an expand/restore button. */\n expandable?: boolean;\n /** Classes applied to the dialog panel. */\n className?: string;\n /** Extra header content rendered before the expand/close buttons. */\n headerSlot?: ReactNode;\n /** Footer content pinned below the scrollable body. */\n footer?: ReactNode;\n /** Modal body content. */\n children: ReactNode;\n};\n\nconst sizeClass: Record<ModalSize, string> = {\n sm: \"max-w-sm max-h-[90vh]\",\n md: \"max-w-md max-h-[90vh]\",\n lg: \"max-w-2xl max-h-[90vh]\",\n xl: \"max-w-4xl max-h-[90vh]\",\n full: \"max-w-[95vw] max-h-[95vh]\",\n};\n\nconst DEFAULT_CONFIRM: Required<ConfirmCloseOptions> = {\n title: \"Discard changes?\",\n message: \"You have unsaved changes. Closing now will discard them.\",\n confirmLabel: \"Discard\",\n cancelLabel: \"Keep editing\",\n};\n\nexport function Modal({\n open,\n onClose,\n confirmClose = false,\n title,\n subtitle,\n size = \"md\",\n closeOnBackdrop = false,\n closeOnEsc = true,\n hideClose = false,\n expandable = true,\n className,\n headerSlot,\n footer,\n children,\n}: ModalProps) {\n const dialogRef = useRef<HTMLDivElement>(null);\n const { isTop, depth } = useModalStack(open);\n const [expanded, setExpanded] = useState(false);\n // When confirmClose is active, a close request opens this prompt instead of\n // closing outright; onClose only fires once the user confirms the discard.\n const [confirming, setConfirming] = useState(false);\n\n // requestClose is the single entry point for every close affordance. With the\n // guard on, it surfaces the confirmation; otherwise it closes immediately.\n const requestClose = () => {\n if (confirmClose) setConfirming(true);\n else onClose();\n };\n\n useEffect(() => {\n if (!open) {\n setExpanded(false);\n setConfirming(false);\n }\n }, [open]);\n\n // A close guard that disappears mid-prompt (changes saved/reverted) should\n // not leave a stale confirmation dialog up.\n useEffect(() => {\n if (!confirmClose) setConfirming(false);\n }, [confirmClose]);\n\n useEffect(() => {\n // Only the topmost modal handles Escape so a keypress closes one nested\n // layer at a time instead of every open modal at once.\n if (!open || !closeOnEsc || !isTop) return;\n const onKey = (e: KeyboardEvent) => {\n if (e.key !== \"Escape\") return;\n // While the prompt is up, Escape dismisses the prompt rather than the modal.\n if (confirming) setConfirming(false);\n else requestClose();\n };\n document.addEventListener(\"keydown\", onKey);\n return () => document.removeEventListener(\"keydown\", onKey);\n }, [open, closeOnEsc, isTop, confirming, confirmClose, onClose]);\n\n useEffect(() => {\n if (!open) return;\n const prev = document.activeElement as HTMLElement | null;\n dialogRef.current?.focus();\n return () => prev?.focus?.();\n }, [open]);\n\n if (!open) return null;\n\n const overlay = (\n <div\n className={cn(\n \"fixed inset-0 flex items-center justify-center\",\n // Nested modals dim less so the dialog they opened over stays visible.\n depth === 0 ? \"bg-black/40\" : \"bg-black/20\",\n )}\n // Above the z-[9999] popover/overlay layer (dropdowns, tooltips, toasts) so a\n // modal opened from one of them stacks on top; +depth keeps nested modals\n // above their parent.\n style={{ zIndex: 10000 + depth * 10 }}\n onClick={closeOnBackdrop ? requestClose : undefined}\n role=\"presentation\"\n >\n <div\n ref={dialogRef}\n tabIndex={-1}\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label={typeof title === \"string\" ? title : undefined}\n className={cn(\n \"relative bg-background border border-border rounded-lg shadow-xl w-full flex flex-col\",\n expanded ? sizeClass.full : sizeClass[size],\n className,\n )}\n onClick={(e) => e.stopPropagation()}\n >\n {(title || subtitle || headerSlot || expandable || !hideClose) && (\n <div className=\"px-density-4 py-density-3 border-b border-border\">\n <div className=\"flex items-center gap-density-2\">\n {title ? (\n <h2 className=\"text-sm font-semibold flex-1\">{title}</h2>\n ) : (\n <span className=\"flex-1\" />\n )}\n {headerSlot}\n {expandable && (\n <button\n type=\"button\"\n onClick={() => setExpanded((v) => !v)}\n aria-label={expanded ? \"Restore size\" : \"Expand to fullscreen\"}\n className=\"text-muted-foreground hover:text-foreground\"\n >\n <Icon icon={expanded ? UiFullscreenFilled : UiFullscreen} />\n </button>\n )}\n {!hideClose && (\n <button\n type=\"button\"\n onClick={requestClose}\n aria-label=\"Close\"\n className=\"text-muted-foreground hover:text-foreground\"\n >\n <Icon icon={UiClose} />\n </button>\n )}\n </div>\n {subtitle ? <div className=\"mt-density-2\">{subtitle}</div> : null}\n </div>\n )}\n <div className=\"flex-1 overflow-auto px-density-4 py-density-3\">{children}</div>\n {footer && <div className=\"px-density-4 py-density-3 border-t border-border\">{footer}</div>}\n {confirming && (\n <ConfirmClosePrompt\n options={confirmClose === true ? DEFAULT_CONFIRM : { ...DEFAULT_CONFIRM, ...confirmClose }}\n onConfirm={() => {\n setConfirming(false);\n onClose();\n }}\n onCancel={() => setConfirming(false)}\n />\n )}\n </div>\n </div>\n );\n\n // Render into document.body so the fixed-position overlay escapes any ancestor\n // transform/overflow (e.g. a dropdown menu positioned via a CSS transform),\n // which would otherwise trap position:fixed inside that ancestor's box and clip\n // the modal to it.\n return typeof document !== \"undefined\" ? createPortal(overlay, document.body) : null;\n}\n\nfunction ConfirmClosePrompt({\n options,\n onConfirm,\n onCancel,\n}: {\n options: Required<ConfirmCloseOptions>;\n onConfirm: () => void;\n onCancel: () => void;\n}) {\n return (\n <div\n className=\"absolute inset-0 z-10 flex items-center justify-center rounded-lg bg-background/80 p-density-4\"\n role=\"alertdialog\"\n aria-modal=\"true\"\n aria-label={typeof options.title === \"string\" ? options.title : \"Confirm close\"}\n onClick={(e) => e.stopPropagation()}\n >\n <div className=\"w-full max-w-sm rounded-lg border border-border bg-background p-density-4 shadow-xl\">\n <h3 className=\"text-sm font-semibold\">{options.title}</h3>\n <p className=\"mt-density-2 text-sm text-muted-foreground\">{options.message}</p>\n <div className=\"mt-density-4 flex justify-end gap-density-2\">\n <Button variant=\"ghost\" size=\"sm\" onClick={onCancel}>\n {options.cancelLabel}\n </Button>\n <Button variant=\"destructive\" size=\"sm\" onClick={onConfirm}>\n {options.confirmLabel}\n </Button>\n </div>\n </div>\n </div>\n );\n}\n"],"names":["_a"],"mappings":"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"}
@@ -0,0 +1,89 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const jsxRuntime = require("react/jsx-runtime");
4
+ const react = require("react");
5
+ const reactDom = require("react-dom");
6
+ const utils = require("../lib/utils.cjs");
7
+ const Icon = require("../data/Icon.cjs");
8
+ const toastContext = require("./toast-context.cjs");
9
+ const UiClose = require("../icons/components/UiClose.cjs");
10
+ const DEFAULT_DURATION_MS = 2200;
11
+ const DOT_TONE = {
12
+ success: "bg-emerald-500",
13
+ danger: "bg-rose-500",
14
+ warning: "bg-amber-500",
15
+ info: "bg-sky-500",
16
+ neutral: "bg-primary"
17
+ };
18
+ function ToastProvider({ children, durationMs = DEFAULT_DURATION_MS }) {
19
+ const [toasts, setToasts] = react.useState([]);
20
+ const idRef = react.useRef(0);
21
+ const timers = react.useRef(/* @__PURE__ */ new Map());
22
+ const dismiss = react.useCallback((id) => {
23
+ setToasts((cur) => cur.filter((t) => t.id !== id));
24
+ const handle = timers.current.get(id);
25
+ if (handle !== void 0) {
26
+ clearTimeout(handle);
27
+ timers.current.delete(id);
28
+ }
29
+ }, []);
30
+ const toast = react.useCallback(
31
+ (options) => {
32
+ const normalized = typeof options === "string" ? { message: options } : options;
33
+ const id = idRef.current += 1;
34
+ setToasts((cur) => [...cur, { tone: "neutral", ...normalized, id }]);
35
+ const ttl = normalized.durationMs ?? durationMs;
36
+ if (ttl > 0) {
37
+ timers.current.set(
38
+ id,
39
+ setTimeout(() => dismiss(id), ttl)
40
+ );
41
+ }
42
+ return id;
43
+ },
44
+ [dismiss, durationMs]
45
+ );
46
+ react.useEffect(() => {
47
+ const pending = timers.current;
48
+ return () => {
49
+ pending.forEach((handle) => clearTimeout(handle));
50
+ pending.clear();
51
+ };
52
+ }, []);
53
+ const value = react.useMemo(() => ({ toast, dismiss }), [toast, dismiss]);
54
+ return /* @__PURE__ */ jsxRuntime.jsxs(toastContext.ToastContext.Provider, { value, children: [
55
+ children,
56
+ typeof document !== "undefined" && reactDom.createPortal(
57
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pointer-events-none fixed inset-x-0 bottom-6 z-[9999] flex flex-col items-center gap-density-2", children: toasts.map((entry) => /* @__PURE__ */ jsxRuntime.jsx(ToastView, { entry, onDismiss: () => dismiss(entry.id) }, entry.id)) }),
58
+ document.body
59
+ )
60
+ ] });
61
+ }
62
+ function ToastView({ entry, onDismiss }) {
63
+ return /* @__PURE__ */ jsxRuntime.jsxs(
64
+ "div",
65
+ {
66
+ role: "status",
67
+ className: utils.cn(
68
+ "pointer-events-auto flex items-center gap-density-2 rounded-md border border-border",
69
+ "bg-popover px-density-3 py-density-2 text-sm font-medium text-popover-foreground shadow-lg"
70
+ ),
71
+ children: [
72
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: utils.cn("h-2 w-2 shrink-0 rounded-full", DOT_TONE[entry.tone ?? "neutral"]) }),
73
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: entry.message }),
74
+ /* @__PURE__ */ jsxRuntime.jsx(
75
+ "button",
76
+ {
77
+ type: "button",
78
+ onClick: onDismiss,
79
+ "aria-label": "Dismiss",
80
+ className: "ml-1 text-muted-foreground transition-colors hover:text-foreground",
81
+ children: /* @__PURE__ */ jsxRuntime.jsx(Icon.Icon, { icon: UiClose.UiClose, className: "h-3 w-3" })
82
+ }
83
+ )
84
+ ]
85
+ }
86
+ );
87
+ }
88
+ exports.ToastProvider = ToastProvider;
89
+ //# sourceMappingURL=Toast.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Toast.cjs","sources":["../../src/overlay/Toast.tsx"],"sourcesContent":["import { useCallback, useEffect, useMemo, useRef, useState, type ReactNode } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { cn } from \"../lib/utils\";\nimport { Icon } from \"../data/Icon\";\nimport { UiClose } from \"../icons\";\nimport {\n ToastContext,\n type ToastEntry,\n type ToastOptions,\n type ToastTone,\n} from \"./toast-context\";\n\nconst DEFAULT_DURATION_MS = 2200;\n\nconst DOT_TONE: Record<ToastTone, string> = {\n success: \"bg-emerald-500\",\n danger: \"bg-rose-500\",\n warning: \"bg-amber-500\",\n info: \"bg-sky-500\",\n neutral: \"bg-primary\",\n};\n\nexport type ToastProviderProps = {\n children: ReactNode;\n /** Default auto-dismiss delay applied when a toast omits `durationMs`. */\n durationMs?: number;\n};\n\n/**\n * Provides the imperative toast API and renders the bottom-center stack into a\n * portal (the Gavel `PRDetail` confirmation toast — a tone dot plus a transient\n * message). Built on clicky tokens; auto-dismisses after `durationMs`. Consume\n * the API with `useToast()` from `./toast-context`.\n */\nexport function ToastProvider({ children, durationMs = DEFAULT_DURATION_MS }: ToastProviderProps) {\n const [toasts, setToasts] = useState<ToastEntry[]>([]);\n const idRef = useRef(0);\n const timers = useRef<Map<number, ReturnType<typeof setTimeout>>>(new Map());\n\n const dismiss = useCallback((id: number) => {\n setToasts((cur) => cur.filter((t) => t.id !== id));\n const handle = timers.current.get(id);\n if (handle !== undefined) {\n clearTimeout(handle);\n timers.current.delete(id);\n }\n }, []);\n\n const toast = useCallback(\n (options: ToastOptions | string) => {\n const normalized: ToastOptions = typeof options === \"string\" ? { message: options } : options;\n const id = (idRef.current += 1);\n setToasts((cur) => [...cur, { tone: \"neutral\", ...normalized, id }]);\n const ttl = normalized.durationMs ?? durationMs;\n if (ttl > 0) {\n timers.current.set(\n id,\n setTimeout(() => dismiss(id), ttl),\n );\n }\n return id;\n },\n [dismiss, durationMs],\n );\n\n useEffect(() => {\n const pending = timers.current;\n return () => {\n pending.forEach((handle) => clearTimeout(handle));\n pending.clear();\n };\n }, []);\n\n const value = useMemo(() => ({ toast, dismiss }), [toast, dismiss]);\n\n return (\n <ToastContext.Provider value={value}>\n {children}\n {typeof document !== \"undefined\" &&\n createPortal(\n <div className=\"pointer-events-none fixed inset-x-0 bottom-6 z-[9999] flex flex-col items-center gap-density-2\">\n {toasts.map((entry) => (\n <ToastView key={entry.id} entry={entry} onDismiss={() => dismiss(entry.id)} />\n ))}\n </div>,\n document.body,\n )}\n </ToastContext.Provider>\n );\n}\n\nfunction ToastView({ entry, onDismiss }: { entry: ToastEntry; onDismiss: () => void }) {\n return (\n <div\n role=\"status\"\n className={cn(\n \"pointer-events-auto flex items-center gap-density-2 rounded-md border border-border\",\n \"bg-popover px-density-3 py-density-2 text-sm font-medium text-popover-foreground shadow-lg\",\n )}\n >\n <span className={cn(\"h-2 w-2 shrink-0 rounded-full\", DOT_TONE[entry.tone ?? \"neutral\"])} />\n <span>{entry.message}</span>\n <button\n type=\"button\"\n onClick={onDismiss}\n aria-label=\"Dismiss\"\n className=\"ml-1 text-muted-foreground transition-colors hover:text-foreground\"\n >\n <Icon icon={UiClose} className=\"h-3 w-3\" />\n </button>\n </div>\n );\n}\n"],"names":["useState","useRef","useCallback","useEffect","useMemo","jsxs","ToastContext","createPortal","jsx","cn","Icon","UiClose"],"mappings":";;;;;;;;;AAYA,MAAM,sBAAsB;AAE5B,MAAM,WAAsC;AAAA,EAC1C,SAAS;AAAA,EACT,QAAQ;AAAA,EACR,SAAS;AAAA,EACT,MAAM;AAAA,EACN,SAAS;AACX;AAcO,SAAS,cAAc,EAAE,UAAU,aAAa,uBAA2C;AAChG,QAAM,CAAC,QAAQ,SAAS,IAAIA,MAAAA,SAAuB,CAAA,CAAE;AACrD,QAAM,QAAQC,MAAAA,OAAO,CAAC;AACtB,QAAM,SAASA,MAAAA,OAAmD,oBAAI,KAAK;AAE3E,QAAM,UAAUC,kBAAY,CAAC,OAAe;AAC1C,cAAU,CAAC,QAAQ,IAAI,OAAO,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC;AACjD,UAAM,SAAS,OAAO,QAAQ,IAAI,EAAE;AACpC,QAAI,WAAW,QAAW;AACxB,mBAAa,MAAM;AACnB,aAAO,QAAQ,OAAO,EAAE;AAAA,IAC1B;AAAA,EACF,GAAG,CAAA,CAAE;AAEL,QAAM,QAAQA,MAAAA;AAAAA,IACZ,CAAC,YAAmC;AAClC,YAAM,aAA2B,OAAO,YAAY,WAAW,EAAE,SAAS,YAAY;AACtF,YAAM,KAAM,MAAM,WAAW;AAC7B,gBAAU,CAAC,QAAQ,CAAC,GAAG,KAAK,EAAE,MAAM,WAAW,GAAG,YAAY,GAAA,CAAI,CAAC;AACnE,YAAM,MAAM,WAAW,cAAc;AACrC,UAAI,MAAM,GAAG;AACX,eAAO,QAAQ;AAAA,UACb;AAAA,UACA,WAAW,MAAM,QAAQ,EAAE,GAAG,GAAG;AAAA,QAAA;AAAA,MAErC;AACA,aAAO;AAAA,IACT;AAAA,IACA,CAAC,SAAS,UAAU;AAAA,EAAA;AAGtBC,QAAAA,UAAU,MAAM;AACd,UAAM,UAAU,OAAO;AACvB,WAAO,MAAM;AACX,cAAQ,QAAQ,CAAC,WAAW,aAAa,MAAM,CAAC;AAChD,cAAQ,MAAA;AAAA,IACV;AAAA,EACF,GAAG,CAAA,CAAE;AAEL,QAAM,QAAQC,cAAQ,OAAO,EAAE,OAAO,YAAY,CAAC,OAAO,OAAO,CAAC;AAElE,SACEC,2BAAAA,KAACC,aAAAA,aAAa,UAAb,EAAsB,OACpB,UAAA;AAAA,IAAA;AAAA,IACA,OAAO,aAAa,eACnBC,SAAAA;AAAAA,MACEC,+BAAC,SAAI,WAAU,kGACZ,iBAAO,IAAI,CAAC,UACXA,+BAAC,WAAA,EAAyB,OAAc,WAAW,MAAM,QAAQ,MAAM,EAAE,KAAzD,MAAM,EAAsD,CAC7E,GACH;AAAA,MACA,SAAS;AAAA,IAAA;AAAA,EACX,GACJ;AAEJ;AAEA,SAAS,UAAU,EAAE,OAAO,aAA2D;AACrF,SACEH,2BAAAA;AAAAA,IAAC;AAAA,IAAA;AAAA,MACC,MAAK;AAAA,MACL,WAAWI,MAAAA;AAAAA,QACT;AAAA,QACA;AAAA,MAAA;AAAA,MAGF,UAAA;AAAA,QAAAD,2BAAAA,IAAC,QAAA,EAAK,WAAWC,SAAG,iCAAiC,SAAS,MAAM,QAAQ,SAAS,CAAC,EAAA,CAAG;AAAA,QACzFD,2BAAAA,IAAC,QAAA,EAAM,UAAA,MAAM,QAAA,CAAQ;AAAA,QACrBA,2BAAAA;AAAAA,UAAC;AAAA,UAAA;AAAA,YACC,MAAK;AAAA,YACL,SAAS;AAAA,YACT,cAAW;AAAA,YACX,WAAU;AAAA,YAEV,UAAAA,2BAAAA,IAACE,WAAA,EAAK,MAAMC,QAAAA,SAAS,WAAU,UAAA,CAAU;AAAA,UAAA;AAAA,QAAA;AAAA,MAC3C;AAAA,IAAA;AAAA,EAAA;AAGN;;"}
@@ -0,0 +1,14 @@
1
+ import { ReactNode } from 'react';
2
+ export type ToastProviderProps = {
3
+ children: ReactNode;
4
+ /** Default auto-dismiss delay applied when a toast omits `durationMs`. */
5
+ durationMs?: number;
6
+ };
7
+ /**
8
+ * Provides the imperative toast API and renders the bottom-center stack into a
9
+ * portal (the Gavel `PRDetail` confirmation toast — a tone dot plus a transient
10
+ * message). Built on clicky tokens; auto-dismisses after `durationMs`. Consume
11
+ * the API with `useToast()` from `./toast-context`.
12
+ */
13
+ export declare function ToastProvider({ children, durationMs }: ToastProviderProps): import("react/jsx-runtime").JSX.Element;
14
+ //# sourceMappingURL=Toast.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Toast.d.ts","sourceRoot":"","sources":["../../src/overlay/Toast.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAqD,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAsB1F,MAAM,MAAM,kBAAkB,GAAG;IAC/B,QAAQ,EAAE,SAAS,CAAC;IACpB,0EAA0E;IAC1E,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,EAAE,QAAQ,EAAE,UAAgC,EAAE,EAAE,kBAAkB,2CAuD/F"}
@@ -0,0 +1,89 @@
1
+ import { jsxs, jsx } from "react/jsx-runtime";
2
+ import { useState, useRef, useCallback, useEffect, useMemo } from "react";
3
+ import { createPortal } from "react-dom";
4
+ import { cn } from "../lib/utils.js";
5
+ import { Icon } from "../data/Icon.js";
6
+ import { ToastContext } from "./toast-context.js";
7
+ import { UiClose } from "../icons/components/UiClose.js";
8
+ const DEFAULT_DURATION_MS = 2200;
9
+ const DOT_TONE = {
10
+ success: "bg-emerald-500",
11
+ danger: "bg-rose-500",
12
+ warning: "bg-amber-500",
13
+ info: "bg-sky-500",
14
+ neutral: "bg-primary"
15
+ };
16
+ function ToastProvider({ children, durationMs = DEFAULT_DURATION_MS }) {
17
+ const [toasts, setToasts] = useState([]);
18
+ const idRef = useRef(0);
19
+ const timers = useRef(/* @__PURE__ */ new Map());
20
+ const dismiss = useCallback((id) => {
21
+ setToasts((cur) => cur.filter((t) => t.id !== id));
22
+ const handle = timers.current.get(id);
23
+ if (handle !== void 0) {
24
+ clearTimeout(handle);
25
+ timers.current.delete(id);
26
+ }
27
+ }, []);
28
+ const toast = useCallback(
29
+ (options) => {
30
+ const normalized = typeof options === "string" ? { message: options } : options;
31
+ const id = idRef.current += 1;
32
+ setToasts((cur) => [...cur, { tone: "neutral", ...normalized, id }]);
33
+ const ttl = normalized.durationMs ?? durationMs;
34
+ if (ttl > 0) {
35
+ timers.current.set(
36
+ id,
37
+ setTimeout(() => dismiss(id), ttl)
38
+ );
39
+ }
40
+ return id;
41
+ },
42
+ [dismiss, durationMs]
43
+ );
44
+ useEffect(() => {
45
+ const pending = timers.current;
46
+ return () => {
47
+ pending.forEach((handle) => clearTimeout(handle));
48
+ pending.clear();
49
+ };
50
+ }, []);
51
+ const value = useMemo(() => ({ toast, dismiss }), [toast, dismiss]);
52
+ return /* @__PURE__ */ jsxs(ToastContext.Provider, { value, children: [
53
+ children,
54
+ typeof document !== "undefined" && createPortal(
55
+ /* @__PURE__ */ jsx("div", { className: "pointer-events-none fixed inset-x-0 bottom-6 z-[9999] flex flex-col items-center gap-density-2", children: toasts.map((entry) => /* @__PURE__ */ jsx(ToastView, { entry, onDismiss: () => dismiss(entry.id) }, entry.id)) }),
56
+ document.body
57
+ )
58
+ ] });
59
+ }
60
+ function ToastView({ entry, onDismiss }) {
61
+ return /* @__PURE__ */ jsxs(
62
+ "div",
63
+ {
64
+ role: "status",
65
+ className: cn(
66
+ "pointer-events-auto flex items-center gap-density-2 rounded-md border border-border",
67
+ "bg-popover px-density-3 py-density-2 text-sm font-medium text-popover-foreground shadow-lg"
68
+ ),
69
+ children: [
70
+ /* @__PURE__ */ jsx("span", { className: cn("h-2 w-2 shrink-0 rounded-full", DOT_TONE[entry.tone ?? "neutral"]) }),
71
+ /* @__PURE__ */ jsx("span", { children: entry.message }),
72
+ /* @__PURE__ */ jsx(
73
+ "button",
74
+ {
75
+ type: "button",
76
+ onClick: onDismiss,
77
+ "aria-label": "Dismiss",
78
+ className: "ml-1 text-muted-foreground transition-colors hover:text-foreground",
79
+ children: /* @__PURE__ */ jsx(Icon, { icon: UiClose, className: "h-3 w-3" })
80
+ }
81
+ )
82
+ ]
83
+ }
84
+ );
85
+ }
86
+ export {
87
+ ToastProvider
88
+ };
89
+ //# sourceMappingURL=Toast.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Toast.js","sources":["../../src/overlay/Toast.tsx"],"sourcesContent":["import { useCallback, useEffect, useMemo, useRef, useState, type ReactNode } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { cn } from \"../lib/utils\";\nimport { Icon } from \"../data/Icon\";\nimport { UiClose } from \"../icons\";\nimport {\n ToastContext,\n type ToastEntry,\n type ToastOptions,\n type ToastTone,\n} from \"./toast-context\";\n\nconst DEFAULT_DURATION_MS = 2200;\n\nconst DOT_TONE: Record<ToastTone, string> = {\n success: \"bg-emerald-500\",\n danger: \"bg-rose-500\",\n warning: \"bg-amber-500\",\n info: \"bg-sky-500\",\n neutral: \"bg-primary\",\n};\n\nexport type ToastProviderProps = {\n children: ReactNode;\n /** Default auto-dismiss delay applied when a toast omits `durationMs`. */\n durationMs?: number;\n};\n\n/**\n * Provides the imperative toast API and renders the bottom-center stack into a\n * portal (the Gavel `PRDetail` confirmation toast — a tone dot plus a transient\n * message). Built on clicky tokens; auto-dismisses after `durationMs`. Consume\n * the API with `useToast()` from `./toast-context`.\n */\nexport function ToastProvider({ children, durationMs = DEFAULT_DURATION_MS }: ToastProviderProps) {\n const [toasts, setToasts] = useState<ToastEntry[]>([]);\n const idRef = useRef(0);\n const timers = useRef<Map<number, ReturnType<typeof setTimeout>>>(new Map());\n\n const dismiss = useCallback((id: number) => {\n setToasts((cur) => cur.filter((t) => t.id !== id));\n const handle = timers.current.get(id);\n if (handle !== undefined) {\n clearTimeout(handle);\n timers.current.delete(id);\n }\n }, []);\n\n const toast = useCallback(\n (options: ToastOptions | string) => {\n const normalized: ToastOptions = typeof options === \"string\" ? { message: options } : options;\n const id = (idRef.current += 1);\n setToasts((cur) => [...cur, { tone: \"neutral\", ...normalized, id }]);\n const ttl = normalized.durationMs ?? durationMs;\n if (ttl > 0) {\n timers.current.set(\n id,\n setTimeout(() => dismiss(id), ttl),\n );\n }\n return id;\n },\n [dismiss, durationMs],\n );\n\n useEffect(() => {\n const pending = timers.current;\n return () => {\n pending.forEach((handle) => clearTimeout(handle));\n pending.clear();\n };\n }, []);\n\n const value = useMemo(() => ({ toast, dismiss }), [toast, dismiss]);\n\n return (\n <ToastContext.Provider value={value}>\n {children}\n {typeof document !== \"undefined\" &&\n createPortal(\n <div className=\"pointer-events-none fixed inset-x-0 bottom-6 z-[9999] flex flex-col items-center gap-density-2\">\n {toasts.map((entry) => (\n <ToastView key={entry.id} entry={entry} onDismiss={() => dismiss(entry.id)} />\n ))}\n </div>,\n document.body,\n )}\n </ToastContext.Provider>\n );\n}\n\nfunction ToastView({ entry, onDismiss }: { entry: ToastEntry; onDismiss: () => void }) {\n return (\n <div\n role=\"status\"\n className={cn(\n \"pointer-events-auto flex items-center gap-density-2 rounded-md border border-border\",\n \"bg-popover px-density-3 py-density-2 text-sm font-medium text-popover-foreground shadow-lg\",\n )}\n >\n <span className={cn(\"h-2 w-2 shrink-0 rounded-full\", DOT_TONE[entry.tone ?? \"neutral\"])} />\n <span>{entry.message}</span>\n <button\n type=\"button\"\n onClick={onDismiss}\n aria-label=\"Dismiss\"\n className=\"ml-1 text-muted-foreground transition-colors hover:text-foreground\"\n >\n <Icon icon={UiClose} className=\"h-3 w-3\" />\n </button>\n </div>\n );\n}\n"],"names":[],"mappings":";;;;;;;AAYA,MAAM,sBAAsB;AAE5B,MAAM,WAAsC;AAAA,EAC1C,SAAS;AAAA,EACT,QAAQ;AAAA,EACR,SAAS;AAAA,EACT,MAAM;AAAA,EACN,SAAS;AACX;AAcO,SAAS,cAAc,EAAE,UAAU,aAAa,uBAA2C;AAChG,QAAM,CAAC,QAAQ,SAAS,IAAI,SAAuB,CAAA,CAAE;AACrD,QAAM,QAAQ,OAAO,CAAC;AACtB,QAAM,SAAS,OAAmD,oBAAI,KAAK;AAE3E,QAAM,UAAU,YAAY,CAAC,OAAe;AAC1C,cAAU,CAAC,QAAQ,IAAI,OAAO,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC;AACjD,UAAM,SAAS,OAAO,QAAQ,IAAI,EAAE;AACpC,QAAI,WAAW,QAAW;AACxB,mBAAa,MAAM;AACnB,aAAO,QAAQ,OAAO,EAAE;AAAA,IAC1B;AAAA,EACF,GAAG,CAAA,CAAE;AAEL,QAAM,QAAQ;AAAA,IACZ,CAAC,YAAmC;AAClC,YAAM,aAA2B,OAAO,YAAY,WAAW,EAAE,SAAS,YAAY;AACtF,YAAM,KAAM,MAAM,WAAW;AAC7B,gBAAU,CAAC,QAAQ,CAAC,GAAG,KAAK,EAAE,MAAM,WAAW,GAAG,YAAY,GAAA,CAAI,CAAC;AACnE,YAAM,MAAM,WAAW,cAAc;AACrC,UAAI,MAAM,GAAG;AACX,eAAO,QAAQ;AAAA,UACb;AAAA,UACA,WAAW,MAAM,QAAQ,EAAE,GAAG,GAAG;AAAA,QAAA;AAAA,MAErC;AACA,aAAO;AAAA,IACT;AAAA,IACA,CAAC,SAAS,UAAU;AAAA,EAAA;AAGtB,YAAU,MAAM;AACd,UAAM,UAAU,OAAO;AACvB,WAAO,MAAM;AACX,cAAQ,QAAQ,CAAC,WAAW,aAAa,MAAM,CAAC;AAChD,cAAQ,MAAA;AAAA,IACV;AAAA,EACF,GAAG,CAAA,CAAE;AAEL,QAAM,QAAQ,QAAQ,OAAO,EAAE,OAAO,YAAY,CAAC,OAAO,OAAO,CAAC;AAElE,SACE,qBAAC,aAAa,UAAb,EAAsB,OACpB,UAAA;AAAA,IAAA;AAAA,IACA,OAAO,aAAa,eACnB;AAAA,MACE,oBAAC,SAAI,WAAU,kGACZ,iBAAO,IAAI,CAAC,UACX,oBAAC,WAAA,EAAyB,OAAc,WAAW,MAAM,QAAQ,MAAM,EAAE,KAAzD,MAAM,EAAsD,CAC7E,GACH;AAAA,MACA,SAAS;AAAA,IAAA;AAAA,EACX,GACJ;AAEJ;AAEA,SAAS,UAAU,EAAE,OAAO,aAA2D;AACrF,SACE;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,MAAK;AAAA,MACL,WAAW;AAAA,QACT;AAAA,QACA;AAAA,MAAA;AAAA,MAGF,UAAA;AAAA,QAAA,oBAAC,QAAA,EAAK,WAAW,GAAG,iCAAiC,SAAS,MAAM,QAAQ,SAAS,CAAC,EAAA,CAAG;AAAA,QACzF,oBAAC,QAAA,EAAM,UAAA,MAAM,QAAA,CAAQ;AAAA,QACrB;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,MAAK;AAAA,YACL,SAAS;AAAA,YACT,cAAW;AAAA,YACX,WAAU;AAAA,YAEV,UAAA,oBAAC,MAAA,EAAK,MAAM,SAAS,WAAU,UAAA,CAAU;AAAA,UAAA;AAAA,QAAA;AAAA,MAC3C;AAAA,IAAA;AAAA,EAAA;AAGN;"}
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const react = require("react");
4
+ const ToastContext = react.createContext(null);
5
+ function useToast() {
6
+ const ctx = react.useContext(ToastContext);
7
+ if (!ctx) throw new Error("useToast must be used within a <ToastProvider>");
8
+ return ctx;
9
+ }
10
+ exports.ToastContext = ToastContext;
11
+ exports.useToast = useToast;
12
+ //# sourceMappingURL=toast-context.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toast-context.cjs","sources":["../../src/overlay/toast-context.ts"],"sourcesContent":["import { createContext, useContext, type ReactNode } from \"react\";\nimport type { BadgeTone } from \"../data/Badge\";\n\nexport type ToastTone = BadgeTone;\n\nexport type ToastOptions = {\n /** Message body. */\n message: ReactNode;\n /** Semantic color of the leading dot. Defaults to `neutral`. */\n tone?: ToastTone;\n /** Auto-dismiss delay in ms. `0` keeps it until dismissed. */\n durationMs?: number;\n};\n\nexport type ToastEntry = ToastOptions & { id: number };\n\nexport type ToastContextValue = {\n /** Show a toast; returns its id. Pass a string for a neutral message. */\n toast: (options: ToastOptions | string) => number;\n /** Dismiss a toast by id. */\n dismiss: (id: number) => void;\n};\n\nexport const ToastContext = createContext<ToastContextValue | null>(null);\n\n/** Access the toast API. Must be called under a `<ToastProvider>`. */\nexport function useToast(): ToastContextValue {\n const ctx = useContext(ToastContext);\n if (!ctx) throw new Error(\"useToast must be used within a <ToastProvider>\");\n return ctx;\n}\n"],"names":["createContext","useContext"],"mappings":";;;AAuBO,MAAM,eAAeA,MAAAA,cAAwC,IAAI;AAGjE,SAAS,WAA8B;AAC5C,QAAM,MAAMC,MAAAA,WAAW,YAAY;AACnC,MAAI,CAAC,IAAK,OAAM,IAAI,MAAM,gDAAgD;AAC1E,SAAO;AACT;;;"}
@@ -0,0 +1,24 @@
1
+ import { ReactNode } from 'react';
2
+ import { BadgeTone } from '../data/Badge';
3
+ export type ToastTone = BadgeTone;
4
+ export type ToastOptions = {
5
+ /** Message body. */
6
+ message: ReactNode;
7
+ /** Semantic color of the leading dot. Defaults to `neutral`. */
8
+ tone?: ToastTone;
9
+ /** Auto-dismiss delay in ms. `0` keeps it until dismissed. */
10
+ durationMs?: number;
11
+ };
12
+ export type ToastEntry = ToastOptions & {
13
+ id: number;
14
+ };
15
+ export type ToastContextValue = {
16
+ /** Show a toast; returns its id. Pass a string for a neutral message. */
17
+ toast: (options: ToastOptions | string) => number;
18
+ /** Dismiss a toast by id. */
19
+ dismiss: (id: number) => void;
20
+ };
21
+ export declare const ToastContext: import('react').Context<ToastContextValue | null>;
22
+ /** Access the toast API. Must be called under a `<ToastProvider>`. */
23
+ export declare function useToast(): ToastContextValue;
24
+ //# sourceMappingURL=toast-context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toast-context.d.ts","sourceRoot":"","sources":["../../src/overlay/toast-context.ts"],"names":[],"mappings":"AAAA,OAAO,EAA6B,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAClE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAE/C,MAAM,MAAM,SAAS,GAAG,SAAS,CAAC;AAElC,MAAM,MAAM,YAAY,GAAG;IACzB,oBAAoB;IACpB,OAAO,EAAE,SAAS,CAAC;IACnB,gEAAgE;IAChE,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,8DAA8D;IAC9D,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG,YAAY,GAAG;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,CAAC;AAEvD,MAAM,MAAM,iBAAiB,GAAG;IAC9B,yEAAyE;IACzE,KAAK,EAAE,CAAC,OAAO,EAAE,YAAY,GAAG,MAAM,KAAK,MAAM,CAAC;IAClD,6BAA6B;IAC7B,OAAO,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;CAC/B,CAAC;AAEF,eAAO,MAAM,YAAY,mDAAgD,CAAC;AAE1E,sEAAsE;AACtE,wBAAgB,QAAQ,IAAI,iBAAiB,CAI5C"}
@@ -0,0 +1,12 @@
1
+ import { useContext, createContext } from "react";
2
+ const ToastContext = createContext(null);
3
+ function useToast() {
4
+ const ctx = useContext(ToastContext);
5
+ if (!ctx) throw new Error("useToast must be used within a <ToastProvider>");
6
+ return ctx;
7
+ }
8
+ export {
9
+ ToastContext,
10
+ useToast
11
+ };
12
+ //# sourceMappingURL=toast-context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toast-context.js","sources":["../../src/overlay/toast-context.ts"],"sourcesContent":["import { createContext, useContext, type ReactNode } from \"react\";\nimport type { BadgeTone } from \"../data/Badge\";\n\nexport type ToastTone = BadgeTone;\n\nexport type ToastOptions = {\n /** Message body. */\n message: ReactNode;\n /** Semantic color of the leading dot. Defaults to `neutral`. */\n tone?: ToastTone;\n /** Auto-dismiss delay in ms. `0` keeps it until dismissed. */\n durationMs?: number;\n};\n\nexport type ToastEntry = ToastOptions & { id: number };\n\nexport type ToastContextValue = {\n /** Show a toast; returns its id. Pass a string for a neutral message. */\n toast: (options: ToastOptions | string) => number;\n /** Dismiss a toast by id. */\n dismiss: (id: number) => void;\n};\n\nexport const ToastContext = createContext<ToastContextValue | null>(null);\n\n/** Access the toast API. Must be called under a `<ToastProvider>`. */\nexport function useToast(): ToastContextValue {\n const ctx = useContext(ToastContext);\n if (!ctx) throw new Error(\"useToast must be used within a <ToastProvider>\");\n return ctx;\n}\n"],"names":[],"mappings":";AAuBO,MAAM,eAAe,cAAwC,IAAI;AAGjE,SAAS,WAA8B;AAC5C,QAAM,MAAM,WAAW,YAAY;AACnC,MAAI,CAAC,IAAK,OAAM,IAAI,MAAM,gDAAgD;AAC1E,SAAO;AACT;"}
@@ -22,14 +22,16 @@ function AcceptPicker({
22
22
  onPreviewModeChange,
23
23
  className
24
24
  }) {
25
+ var _a;
25
26
  const rootRef = react.useRef(null);
26
27
  const [open, setOpen] = react.useState(false);
27
28
  const pad = size === "sm" ? "px-2 py-0.5" : "px-2.5 py-1";
29
+ const activeLabel = ((_a = options.find((opt) => opt.value === value)) == null ? void 0 : _a.label) ?? value;
28
30
  react.useEffect(() => {
29
31
  if (!open) return;
30
32
  const onPointerDown = (event) => {
31
- var _a;
32
- if (!((_a = rootRef.current) == null ? void 0 : _a.contains(event.target))) {
33
+ var _a2;
34
+ if (!((_a2 = rootRef.current) == null ? void 0 : _a2.contains(event.target))) {
33
35
  setOpen(false);
34
36
  }
35
37
  };
@@ -43,70 +45,91 @@ function AcceptPicker({
43
45
  document.removeEventListener("keydown", onKeyDown);
44
46
  };
45
47
  }, [open]);
46
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { ref: rootRef, className: utils.cn("relative flex flex-wrap gap-1", className), children: [
47
- options.map((opt) => /* @__PURE__ */ jsxRuntime.jsx(
48
- "button",
48
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { ref: rootRef, className: utils.cn("relative flex", className), children: [
49
+ /* @__PURE__ */ jsxRuntime.jsxs(
50
+ button.Button,
49
51
  {
50
52
  type: "button",
51
- onClick: () => onChange(opt.value),
52
- className: utils.cn(
53
- "rounded-md border text-xs transition-colors",
54
- pad,
55
- value === opt.value ? "border-emerald-500 bg-emerald-50 font-medium text-emerald-700 dark:border-emerald-600 dark:bg-emerald-950/30 dark:text-emerald-400" : "text-muted-foreground hover:border-foreground/20 hover:text-foreground"
56
- ),
57
- children: opt.label
58
- },
59
- opt.value
60
- )),
61
- onPreviewModeChange && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
62
- /* @__PURE__ */ jsxRuntime.jsx(
63
- button.Button,
64
- {
65
- type: "button",
66
- variant: "outline",
67
- size: "sm",
68
- "aria-label": "Open preview menu",
69
- "aria-haspopup": "menu",
70
- "aria-expanded": open,
71
- className: utils.cn("h-auto", pad),
72
- onClick: () => setOpen((current) => !current),
73
- children: /* @__PURE__ */ jsxRuntime.jsx(Icon.Icon, { icon: UiEllipsis.UiEllipsis })
74
- }
75
- ),
76
- open && /* @__PURE__ */ jsxRuntime.jsx(
77
- "div",
78
- {
79
- role: "menu",
80
- "aria-label": "Preview options",
81
- className: "absolute right-0 top-[calc(100%+0.375rem)] z-50 min-w-[12rem] rounded-md border border-border bg-popover p-1 text-popover-foreground shadow-lg shadow-black/5",
82
- children: PREVIEW_OPTIONS.map((option) => {
83
- const active = option.value === previewMode;
84
- return /* @__PURE__ */ jsxRuntime.jsxs(
85
- "button",
53
+ variant: "outline",
54
+ size: "sm",
55
+ "aria-label": "Open format menu",
56
+ "aria-haspopup": "menu",
57
+ "aria-expanded": open,
58
+ className: utils.cn("h-auto gap-1.5", pad),
59
+ onClick: () => setOpen((current) => !current),
60
+ children: [
61
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-medium", children: activeLabel }),
62
+ /* @__PURE__ */ jsxRuntime.jsx(Icon.Icon, { icon: UiEllipsis.UiEllipsis, className: "text-muted-foreground" })
63
+ ]
64
+ }
65
+ ),
66
+ open && /* @__PURE__ */ jsxRuntime.jsxs(
67
+ "div",
68
+ {
69
+ role: "menu",
70
+ "aria-label": "Format and preview options",
71
+ className: "absolute right-0 top-[calc(100%+0.375rem)] z-50 min-w-[12rem] rounded-md border border-border bg-popover p-1 text-popover-foreground shadow-lg shadow-black/5",
72
+ children: [
73
+ /* @__PURE__ */ jsxRuntime.jsx(MenuSectionLabel, { children: "Format" }),
74
+ options.map((opt) => /* @__PURE__ */ jsxRuntime.jsx(
75
+ MenuRadioItem,
76
+ {
77
+ label: opt.label,
78
+ active: opt.value === value,
79
+ onSelect: () => {
80
+ onChange(opt.value);
81
+ setOpen(false);
82
+ }
83
+ },
84
+ opt.value
85
+ )),
86
+ onPreviewModeChange && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
87
+ /* @__PURE__ */ jsxRuntime.jsx("div", { role: "separator", className: "my-1 h-px bg-border" }),
88
+ /* @__PURE__ */ jsxRuntime.jsx(MenuSectionLabel, { children: "Preview" }),
89
+ PREVIEW_OPTIONS.map((option) => /* @__PURE__ */ jsxRuntime.jsx(
90
+ MenuRadioItem,
86
91
  {
87
- type: "button",
88
- role: "menuitemradio",
89
- "aria-checked": active,
90
- className: utils.cn(
91
- "flex w-full items-center gap-2 rounded-sm px-2 py-1.5 text-left text-sm transition-colors",
92
- "hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground focus:outline-none"
93
- ),
94
- onClick: () => {
92
+ label: option.label,
93
+ active: option.value === previewMode,
94
+ onSelect: () => {
95
95
  onPreviewModeChange(option.value);
96
96
  setOpen(false);
97
- },
98
- children: [
99
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "min-w-0 flex-1", children: option.label }),
100
- active ? /* @__PURE__ */ jsxRuntime.jsx(Icon.Icon, { icon: UiCheck.UiCheck, className: "shrink-0" }) : null
101
- ]
97
+ }
102
98
  },
103
99
  option.value
104
- );
105
- })
106
- }
107
- )
108
- ] })
100
+ ))
101
+ ] })
102
+ ]
103
+ }
104
+ )
109
105
  ] });
110
106
  }
107
+ function MenuSectionLabel({ children }) {
108
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-2 py-1 text-[10px] font-semibold uppercase tracking-wider text-muted-foreground", children });
109
+ }
110
+ function MenuRadioItem({
111
+ label,
112
+ active,
113
+ onSelect
114
+ }) {
115
+ return /* @__PURE__ */ jsxRuntime.jsxs(
116
+ "button",
117
+ {
118
+ type: "button",
119
+ role: "menuitemradio",
120
+ "aria-checked": active,
121
+ className: utils.cn(
122
+ "flex w-full items-center gap-2 rounded-sm px-2 py-1.5 text-left text-sm transition-colors",
123
+ "hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground focus:outline-none",
124
+ active && "font-medium"
125
+ ),
126
+ onClick: onSelect,
127
+ children: [
128
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "min-w-0 flex-1", children: label }),
129
+ active ? /* @__PURE__ */ jsxRuntime.jsx(Icon.Icon, { icon: UiCheck.UiCheck, className: "shrink-0" }) : null
130
+ ]
131
+ }
132
+ );
133
+ }
111
134
  exports.AcceptPicker = AcceptPicker;
112
135
  //# sourceMappingURL=AcceptPicker.cjs.map