@flanksource/clicky-ui 0.2.18 → 0.2.20

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 (445) 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 +21 -1
  61. package/dist/components.cjs.map +1 -1
  62. package/dist/components.d.ts +11 -1
  63. package/dist/components.d.ts.map +1 -1
  64. package/dist/components.js +21 -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/TabButton.cjs +17 -2
  101. package/dist/data/TabButton.cjs.map +1 -1
  102. package/dist/data/TabButton.d.ts +5 -1
  103. package/dist/data/TabButton.d.ts.map +1 -1
  104. package/dist/data/TabButton.js +17 -2
  105. package/dist/data/TabButton.js.map +1 -1
  106. package/dist/data/Timeline.cjs +61 -0
  107. package/dist/data/Timeline.cjs.map +1 -0
  108. package/dist/data/Timeline.d.ts +36 -0
  109. package/dist/data/Timeline.d.ts.map +1 -0
  110. package/dist/data/Timeline.js +61 -0
  111. package/dist/data/Timeline.js.map +1 -0
  112. package/dist/data/TimeseriesCoreBars.cjs +2 -25
  113. package/dist/data/TimeseriesCoreBars.cjs.map +1 -1
  114. package/dist/data/TimeseriesCoreBars.d.ts +0 -19
  115. package/dist/data/TimeseriesCoreBars.d.ts.map +1 -1
  116. package/dist/data/TimeseriesCoreBars.js +2 -25
  117. package/dist/data/TimeseriesCoreBars.js.map +1 -1
  118. package/dist/data/TimeseriesCoreBars.model.cjs +27 -0
  119. package/dist/data/TimeseriesCoreBars.model.cjs.map +1 -0
  120. package/dist/data/TimeseriesCoreBars.model.d.ts +20 -0
  121. package/dist/data/TimeseriesCoreBars.model.d.ts.map +1 -0
  122. package/dist/data/TimeseriesCoreBars.model.js +27 -0
  123. package/dist/data/TimeseriesCoreBars.model.js.map +1 -0
  124. package/dist/data/TimeseriesPanel.axes.cjs.map +1 -1
  125. package/dist/data/TimeseriesPanel.axes.d.ts +1 -1
  126. package/dist/data/TimeseriesPanel.axes.d.ts.map +1 -1
  127. package/dist/data/TimeseriesPanel.axes.js.map +1 -1
  128. package/dist/data/TimeseriesPanel.cjs +4 -54
  129. package/dist/data/TimeseriesPanel.cjs.map +1 -1
  130. package/dist/data/TimeseriesPanel.d.ts +2 -138
  131. package/dist/data/TimeseriesPanel.d.ts.map +1 -1
  132. package/dist/data/TimeseriesPanel.js +2 -52
  133. package/dist/data/TimeseriesPanel.js.map +1 -1
  134. package/dist/data/TimeseriesPanel.model.cjs +53 -0
  135. package/dist/data/TimeseriesPanel.model.cjs.map +1 -0
  136. package/dist/data/TimeseriesPanel.model.d.ts +88 -0
  137. package/dist/data/TimeseriesPanel.model.d.ts.map +1 -0
  138. package/dist/data/TimeseriesPanel.model.js +53 -0
  139. package/dist/data/TimeseriesPanel.model.js.map +1 -0
  140. package/dist/data/Tree.cjs +1 -1
  141. package/dist/data/Tree.cjs.map +1 -1
  142. package/dist/data/Tree.js +1 -1
  143. package/dist/data/Tree.js.map +1 -1
  144. package/dist/data/ai/ChatFab.cjs +29 -0
  145. package/dist/data/ai/ChatFab.cjs.map +1 -0
  146. package/dist/data/ai/ChatFab.d.ts +12 -0
  147. package/dist/data/ai/ChatFab.d.ts.map +1 -0
  148. package/dist/data/ai/ChatFab.js +29 -0
  149. package/dist/data/ai/ChatFab.js.map +1 -0
  150. package/dist/data/ai/ChatWindow.cjs +178 -0
  151. package/dist/data/ai/ChatWindow.cjs.map +1 -0
  152. package/dist/data/ai/ChatWindow.d.ts +38 -0
  153. package/dist/data/ai/ChatWindow.d.ts.map +1 -0
  154. package/dist/data/ai/ChatWindow.js +156 -0
  155. package/dist/data/ai/ChatWindow.js.map +1 -0
  156. package/dist/data/ai/ChatWindowManager.cjs +139 -0
  157. package/dist/data/ai/ChatWindowManager.cjs.map +1 -0
  158. package/dist/data/ai/ChatWindowManager.d.ts +12 -0
  159. package/dist/data/ai/ChatWindowManager.d.ts.map +1 -0
  160. package/dist/data/ai/ChatWindowManager.js +139 -0
  161. package/dist/data/ai/ChatWindowManager.js.map +1 -0
  162. package/dist/data/ai/ContextBadges.cjs +74 -0
  163. package/dist/data/ai/ContextBadges.cjs.map +1 -0
  164. package/dist/data/ai/ContextBadges.d.ts +16 -0
  165. package/dist/data/ai/ContextBadges.d.ts.map +1 -0
  166. package/dist/data/ai/ContextBadges.js +74 -0
  167. package/dist/data/ai/ContextBadges.js.map +1 -0
  168. package/dist/data/ai/ThreadPicker.cjs +148 -0
  169. package/dist/data/ai/ThreadPicker.cjs.map +1 -0
  170. package/dist/data/ai/ThreadPicker.d.ts +37 -0
  171. package/dist/data/ai/ThreadPicker.d.ts.map +1 -0
  172. package/dist/data/ai/ThreadPicker.js +148 -0
  173. package/dist/data/ai/ThreadPicker.js.map +1 -0
  174. package/dist/data/ai/ToolPreferences.cjs +80 -0
  175. package/dist/data/ai/ToolPreferences.cjs.map +1 -0
  176. package/dist/data/ai/ToolPreferences.d.ts +19 -0
  177. package/dist/data/ai/ToolPreferences.d.ts.map +1 -0
  178. package/dist/data/ai/ToolPreferences.js +80 -0
  179. package/dist/data/ai/ToolPreferences.js.map +1 -0
  180. package/dist/data/ai/chat-window-context.cjs +78 -0
  181. package/dist/data/ai/chat-window-context.cjs.map +1 -0
  182. package/dist/data/ai/chat-window-context.d.ts +57 -0
  183. package/dist/data/ai/chat-window-context.d.ts.map +1 -0
  184. package/dist/data/ai/chat-window-context.js +78 -0
  185. package/dist/data/ai/chat-window-context.js.map +1 -0
  186. package/dist/data/ai/context.cjs +43 -0
  187. package/dist/data/ai/context.cjs.map +1 -0
  188. package/dist/data/ai/context.d.ts +35 -0
  189. package/dist/data/ai/context.d.ts.map +1 -0
  190. package/dist/data/ai/context.js +43 -0
  191. package/dist/data/ai/context.js.map +1 -0
  192. package/dist/data/ai/index.d.ts +10 -0
  193. package/dist/data/ai/index.d.ts.map +1 -0
  194. package/dist/data/cache-browser/CacheDetailPanel.cjs +15 -0
  195. package/dist/data/cache-browser/CacheDetailPanel.cjs.map +1 -1
  196. package/dist/data/cache-browser/CacheDetailPanel.d.ts.map +1 -1
  197. package/dist/data/cache-browser/CacheDetailPanel.js +15 -0
  198. package/dist/data/cache-browser/CacheDetailPanel.js.map +1 -1
  199. package/dist/data/cache-browser/cache-browser.fixtures.d.ts +10 -0
  200. package/dist/data/cache-browser/cache-browser.fixtures.d.ts.map +1 -0
  201. package/dist/data/cache-browser/download.cjs +13 -0
  202. package/dist/data/cache-browser/download.cjs.map +1 -0
  203. package/dist/data/cache-browser/download.d.ts +3 -0
  204. package/dist/data/cache-browser/download.d.ts.map +1 -0
  205. package/dist/data/cache-browser/download.js +13 -0
  206. package/dist/data/cache-browser/download.js.map +1 -0
  207. package/dist/data/chat/Chat.cjs +40 -2
  208. package/dist/data/chat/Chat.cjs.map +1 -1
  209. package/dist/data/chat/Chat.d.ts +5 -2
  210. package/dist/data/chat/Chat.d.ts.map +1 -1
  211. package/dist/data/chat/Chat.fixtures.cjs +86 -0
  212. package/dist/data/chat/Chat.fixtures.cjs.map +1 -0
  213. package/dist/data/chat/Chat.fixtures.d.ts +4 -0
  214. package/dist/data/chat/Chat.fixtures.d.ts.map +1 -1
  215. package/dist/data/chat/Chat.fixtures.js +86 -0
  216. package/dist/data/chat/Chat.fixtures.js.map +1 -0
  217. package/dist/data/chat/Chat.js +41 -3
  218. package/dist/data/chat/Chat.js.map +1 -1
  219. package/dist/data/chat/ContextUsage.cjs +99 -0
  220. package/dist/data/chat/ContextUsage.cjs.map +1 -0
  221. package/dist/data/chat/ContextUsage.d.ts +19 -0
  222. package/dist/data/chat/ContextUsage.d.ts.map +1 -0
  223. package/dist/data/chat/ContextUsage.js +99 -0
  224. package/dist/data/chat/ContextUsage.js.map +1 -0
  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 +14 -6
  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 +57 -7
  305. package/dist/index.cjs.map +1 -1
  306. package/dist/index.js +56 -6
  307. package/dist/index.js.map +1 -1
  308. package/dist/layout/AppShell.cjs +332 -0
  309. package/dist/layout/AppShell.cjs.map +1 -0
  310. package/dist/layout/AppShell.d.ts +75 -0
  311. package/dist/layout/AppShell.d.ts.map +1 -0
  312. package/dist/layout/AppShell.js +332 -0
  313. package/dist/layout/AppShell.js.map +1 -0
  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/layout/Panel.cjs +66 -0
  321. package/dist/layout/Panel.cjs.map +1 -0
  322. package/dist/layout/Panel.d.ts +34 -0
  323. package/dist/layout/Panel.d.ts.map +1 -0
  324. package/dist/layout/Panel.js +66 -0
  325. package/dist/layout/Panel.js.map +1 -0
  326. package/dist/layout/Tabs.cjs +36 -0
  327. package/dist/layout/Tabs.cjs.map +1 -0
  328. package/dist/layout/Tabs.d.ts +36 -0
  329. package/dist/layout/Tabs.d.ts.map +1 -0
  330. package/dist/layout/Tabs.js +36 -0
  331. package/dist/layout/Tabs.js.map +1 -0
  332. package/dist/overlay/DropdownMenu.cjs.map +1 -1
  333. package/dist/overlay/DropdownMenu.d.ts.map +1 -1
  334. package/dist/overlay/DropdownMenu.js.map +1 -1
  335. package/dist/overlay/Modal.cjs +4 -2
  336. package/dist/overlay/Modal.cjs.map +1 -1
  337. package/dist/overlay/Modal.d.ts +1 -1
  338. package/dist/overlay/Modal.d.ts.map +1 -1
  339. package/dist/overlay/Modal.js +4 -2
  340. package/dist/overlay/Modal.js.map +1 -1
  341. package/dist/overlay/Toast.cjs +89 -0
  342. package/dist/overlay/Toast.cjs.map +1 -0
  343. package/dist/overlay/Toast.d.ts +14 -0
  344. package/dist/overlay/Toast.d.ts.map +1 -0
  345. package/dist/overlay/Toast.js +89 -0
  346. package/dist/overlay/Toast.js.map +1 -0
  347. package/dist/overlay/toast-context.cjs +12 -0
  348. package/dist/overlay/toast-context.cjs.map +1 -0
  349. package/dist/overlay/toast-context.d.ts +24 -0
  350. package/dist/overlay/toast-context.d.ts.map +1 -0
  351. package/dist/overlay/toast-context.js +12 -0
  352. package/dist/overlay/toast-context.js.map +1 -0
  353. package/dist/rpc/AcceptPicker.cjs +81 -58
  354. package/dist/rpc/AcceptPicker.cjs.map +1 -1
  355. package/dist/rpc/AcceptPicker.d.ts.map +1 -1
  356. package/dist/rpc/AcceptPicker.js +81 -58
  357. package/dist/rpc/AcceptPicker.js.map +1 -1
  358. package/dist/rpc/CommandForm.cjs +5 -35
  359. package/dist/rpc/CommandForm.cjs.map +1 -1
  360. package/dist/rpc/CommandForm.d.ts +0 -3
  361. package/dist/rpc/CommandForm.d.ts.map +1 -1
  362. package/dist/rpc/CommandForm.js +2 -32
  363. package/dist/rpc/CommandForm.js.map +1 -1
  364. package/dist/rpc/CommandOutput.cjs +2 -1
  365. package/dist/rpc/CommandOutput.cjs.map +1 -1
  366. package/dist/rpc/CommandOutput.d.ts.map +1 -1
  367. package/dist/rpc/CommandOutput.js +2 -1
  368. package/dist/rpc/CommandOutput.js.map +1 -1
  369. package/dist/rpc/EntityExplorerApp.cjs +28 -83
  370. package/dist/rpc/EntityExplorerApp.cjs.map +1 -1
  371. package/dist/rpc/EntityExplorerApp.d.ts +1 -4
  372. package/dist/rpc/EntityExplorerApp.d.ts.map +1 -1
  373. package/dist/rpc/EntityExplorerApp.js +13 -68
  374. package/dist/rpc/EntityExplorerApp.js.map +1 -1
  375. package/dist/rpc/OperationCatalog.cjs +2 -2
  376. package/dist/rpc/OperationCatalog.cjs.map +1 -1
  377. package/dist/rpc/OperationCatalog.d.ts +1 -1
  378. package/dist/rpc/OperationCatalog.d.ts.map +1 -1
  379. package/dist/rpc/OperationCatalog.js +1 -1
  380. package/dist/rpc/OperationCatalog.js.map +1 -1
  381. package/dist/rpc/OperationCommandPage.cjs +6 -4
  382. package/dist/rpc/OperationCommandPage.cjs.map +1 -1
  383. package/dist/rpc/OperationCommandPage.d.ts.map +1 -1
  384. package/dist/rpc/OperationCommandPage.js +3 -1
  385. package/dist/rpc/OperationCommandPage.js.map +1 -1
  386. package/dist/rpc/RouterProvider.cjs +10 -0
  387. package/dist/rpc/RouterProvider.cjs.map +1 -0
  388. package/dist/rpc/RouterProvider.d.ts +10 -0
  389. package/dist/rpc/RouterProvider.d.ts.map +1 -0
  390. package/dist/rpc/RouterProvider.js +10 -0
  391. package/dist/rpc/RouterProvider.js.map +1 -0
  392. package/dist/rpc/apiClient.cjs +4 -4
  393. package/dist/rpc/apiClient.cjs.map +1 -1
  394. package/dist/rpc/apiClient.js +4 -4
  395. package/dist/rpc/apiClient.js.map +1 -1
  396. package/dist/rpc/command-form-utils.cjs +43 -0
  397. package/dist/rpc/command-form-utils.cjs.map +1 -0
  398. package/dist/rpc/command-form-utils.d.ts +5 -0
  399. package/dist/rpc/command-form-utils.d.ts.map +1 -0
  400. package/dist/rpc/command-form-utils.js +43 -0
  401. package/dist/rpc/command-form-utils.js.map +1 -0
  402. package/dist/rpc/commandHref.cjs +62 -0
  403. package/dist/rpc/commandHref.cjs.map +1 -0
  404. package/dist/rpc/commandHref.d.ts +7 -0
  405. package/dist/rpc/commandHref.d.ts.map +1 -0
  406. package/dist/rpc/commandHref.js +62 -0
  407. package/dist/rpc/commandHref.js.map +1 -0
  408. package/dist/rpc/formMetadata.cjs +1 -1
  409. package/dist/rpc/formMetadata.cjs.map +1 -1
  410. package/dist/rpc/formMetadata.js +1 -1
  411. package/dist/rpc/formMetadata.js.map +1 -1
  412. package/dist/rpc/router.cjs +83 -0
  413. package/dist/rpc/router.cjs.map +1 -0
  414. package/dist/rpc/router.d.ts +24 -0
  415. package/dist/rpc/router.d.ts.map +1 -0
  416. package/dist/rpc/router.js +83 -0
  417. package/dist/rpc/router.js.map +1 -0
  418. package/dist/rpc/rpc-story-fixtures/orders.fixture.d.ts +3 -0
  419. package/dist/rpc/rpc-story-fixtures/orders.fixture.d.ts.map +1 -0
  420. package/dist/rpc/rpc-story-fixtures/services.fixture.d.ts +3 -0
  421. package/dist/rpc/rpc-story-fixtures/services.fixture.d.ts.map +1 -0
  422. package/dist/rpc/rpc-story-fixtures/surface-fixture.d.ts +24 -0
  423. package/dist/rpc/rpc-story-fixtures/surface-fixture.d.ts.map +1 -0
  424. package/dist/rpc/rpc-story-fixtures/widgets.fixture.d.ts +3 -0
  425. package/dist/rpc/rpc-story-fixtures/widgets.fixture.d.ts.map +1 -0
  426. package/dist/rpc/rpc-story.fixtures.d.ts +16 -0
  427. package/dist/rpc/rpc-story.fixtures.d.ts.map +1 -0
  428. package/dist/rpc.cjs +17 -0
  429. package/dist/rpc.cjs.map +1 -1
  430. package/dist/rpc.d.ts +5 -0
  431. package/dist/rpc.d.ts.map +1 -1
  432. package/dist/rpc.js +18 -1
  433. package/dist/rpc.js.map +1 -1
  434. package/dist/styles.cjs +1 -0
  435. package/dist/styles.cjs.map +1 -1
  436. package/dist/styles.css +1 -1
  437. package/dist/styles.d.ts.map +1 -1
  438. package/dist/styles.js +1 -0
  439. package/dist/styles.js.map +1 -1
  440. package/dist/tailwind-preset.cjs +36 -19
  441. package/dist/tailwind-preset.cjs.map +1 -1
  442. package/dist/tailwind-preset.d.ts.map +1 -1
  443. package/dist/tailwind-preset.js +36 -19
  444. package/dist/tailwind-preset.js.map +1 -1
  445. package/package.json +11 -1
@@ -4,6 +4,7 @@ const jsxRuntime = require("react/jsx-runtime");
4
4
  const utils = require("../lib/utils.cjs");
5
5
  const size = require("../lib/size.cjs");
6
6
  const useDensity = require("../hooks/use-density.cjs");
7
+ const iconFallback = require("./icon-fallback.cjs");
7
8
  const TONE_CLASSES = {
8
9
  emerald: "text-emerald-700 ring-emerald-200/80 dark:text-emerald-400 dark:ring-emerald-500/30",
9
10
  amber: "text-amber-700 ring-amber-200/80 dark:text-amber-400 dark:ring-amber-500/30",
@@ -14,10 +15,6 @@ const TONE_CLASSES = {
14
15
  neutral: "text-foreground ring-border"
15
16
  };
16
17
  const DEFAULT_PLAIN_ICON_SIZE = "1em";
17
- let fallbackIcon = null;
18
- function setFallbackIconProvider(component) {
19
- fallbackIcon = component;
20
- }
21
18
  function renderImportedGlyph(ImportedIcon, glyphWidth, glyphHeight, rotate, flip, inline, glyphClassName, title) {
22
19
  const transform = [
23
20
  typeof rotate === "number" ? `rotate(${rotate}deg)` : typeof rotate === "string" ? rotate : "",
@@ -37,6 +34,7 @@ function renderImportedGlyph(ImportedIcon, glyphWidth, glyphHeight, rotate, flip
37
34
  );
38
35
  }
39
36
  function renderRuntimeGlyph(name, glyphWidth, glyphHeight, glyphClassName, title) {
37
+ const fallbackIcon = iconFallback.getFallbackIconProvider();
40
38
  if (fallbackIcon) {
41
39
  const Fallback = fallbackIcon;
42
40
  const glyphSize = typeof glyphWidth === "number" ? glyphWidth : glyphHeight;
@@ -136,5 +134,4 @@ function LabelIcon({
136
134
  }
137
135
  exports.Icon = Icon;
138
136
  exports.LabelIcon = LabelIcon;
139
- exports.setFallbackIconProvider = setFallbackIconProvider;
140
137
  //# sourceMappingURL=Icon.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"Icon.cjs","sources":["../../src/data/Icon.tsx"],"sourcesContent":["import type { CSSProperties, ComponentType, ElementType, ReactNode } from \"react\";\nimport { cn } from \"../lib/utils\";\nimport { resolveSize, type SizeToken } from \"../lib/size\";\nimport { useDensityValue } from \"../hooks/use-density\";\n\n// LabelIconSpec is the icon a label may carry: an iconify/runtime name (resolved\n// via the fallback provider) or a fully-rendered node the caller supplies.\nexport type LabelIconSpec = string | ReactNode;\n\nexport type IconStyle = \"plain\" | \"badge\";\n\nexport type IconTone = \"emerald\" | \"amber\" | \"rose\" | \"slate\" | \"sky\" | \"violet\" | \"neutral\";\n\nexport type StaticIconComponent = ElementType;\n\ntype CommonIconProps = {\n /** Classes applied to the glyph or badge wrapper. */\n className?: string;\n /** Explicit glyph width. */\n width?: string | number;\n /** Explicit glyph height. */\n height?: string | number;\n /** CSS rotate value or degrees. */\n rotate?: string | number;\n /** Flip direction for imported glyphs. */\n flip?: string;\n /** Forward inline rendering semantics to imported glyphs. */\n inline?: boolean;\n /** Accessible title for the glyph. */\n title?: string;\n /**\n * Presentation style. `plain` (default) renders the icon inline.\n * `badge` wraps the icon in a circular chip (white background, ring, shadow)\n * sized by `size` — use in stage/approval cells so the chip scales with a\n * neighbouring avatar.\n */\n style?: IconStyle;\n /**\n * Named size token (xxs..xxl). Drives the badge diameter and glyph. The\n * glyph is always ~50% of the badge diameter so it scales consistently\n * across sizes. For `style=\"plain\"` it sets width/height when neither is\n * provided.\n */\n size?: SizeToken;\n /** Semantic color for `style=\"badge\"`. Ignored for plain icons. */\n tone?: IconTone;\n};\n\nexport type IconProps = CommonIconProps &\n (\n | {\n /** Imported static icon component. */\n icon: StaticIconComponent;\n name?: never;\n }\n | {\n /** Runtime icon name resolved by the fallback provider. */\n name: string;\n icon?: never;\n }\n );\n\nconst TONE_CLASSES: Record<IconTone, string> = {\n emerald: \"text-emerald-700 ring-emerald-200/80 dark:text-emerald-400 dark:ring-emerald-500/30\",\n amber: \"text-amber-700 ring-amber-200/80 dark:text-amber-400 dark:ring-amber-500/30\",\n rose: \"text-rose-700 ring-rose-200/80 dark:text-rose-400 dark:ring-rose-500/30\",\n slate: \"text-slate-700 ring-slate-200/80 dark:text-slate-300 dark:ring-slate-500/30\",\n sky: \"text-sky-700 ring-sky-200/80 dark:text-sky-400 dark:ring-sky-500/30\",\n violet: \"text-violet-700 ring-violet-200/80 dark:text-violet-400 dark:ring-violet-500/30\",\n neutral: \"text-foreground ring-border\",\n};\n\nconst DEFAULT_PLAIN_ICON_SIZE = \"1em\";\n\n/**\n * Optional secondary icon provider for user-supplied runtime names.\n * Built-in/default icons should pass an imported component via `icon`.\n */\nexport type FallbackIconProps = {\n /** Runtime icon name to resolve. */\n name?: string;\n /** Classes applied by Icon. */\n className?: string;\n /** Requested glyph size. */\n size?: string | number;\n /** Accessible label. */\n alt?: string;\n};\n\ntype FallbackIconComponent = ComponentType<FallbackIconProps>;\n\nlet fallbackIcon: FallbackIconComponent | null = null;\n\n/**\n * Register a secondary glyph provider. Pass the flanksource Icon/ResourceIcon\n * (or any compatible component) to resolve user-supplied runtime names.\n */\nexport function setFallbackIconProvider(component: FallbackIconComponent | null): void {\n fallbackIcon = component;\n}\n\nfunction renderImportedGlyph(\n ImportedIcon: StaticIconComponent,\n glyphWidth: number | string | undefined,\n glyphHeight: number | string | undefined,\n rotate: string | number | undefined,\n flip: string | undefined,\n inline: boolean | undefined,\n glyphClassName: string | undefined,\n title: string | undefined,\n): JSX.Element {\n const transform = [\n typeof rotate === \"number\" ? `rotate(${rotate}deg)` : typeof rotate === \"string\" ? rotate : \"\",\n flip === \"horizontal\" || flip === \"both\" ? \"scaleX(-1)\" : \"\",\n flip === \"vertical\" || flip === \"both\" ? \"scaleY(-1)\" : \"\",\n ]\n .filter(Boolean)\n .join(\" \");\n\n return (\n <ImportedIcon\n {...(glyphClassName ? { className: glyphClassName } : {})}\n {...(glyphWidth != null ? { width: glyphWidth } : {})}\n {...(glyphHeight != null ? { height: glyphHeight } : {})}\n {...(inline != null ? { \"aria-hidden\": !title } : {})}\n {...(title ? { title, role: \"img\" } : { \"aria-hidden\": true })}\n {...(transform ? { style: { transform } } : {})}\n />\n );\n}\n\nfunction renderRuntimeGlyph(\n name: string,\n glyphWidth: number | string | undefined,\n glyphHeight: number | string | undefined,\n glyphClassName: string | undefined,\n title: string | undefined,\n): JSX.Element {\n if (fallbackIcon) {\n const Fallback = fallbackIcon;\n const glyphSize = typeof glyphWidth === \"number\" ? glyphWidth : glyphHeight;\n return (\n <Fallback\n name={name}\n {...(glyphClassName ? { className: glyphClassName } : {})}\n {...(glyphSize != null ? { size: glyphSize } : {})}\n {...(title ? { alt: title } : {})}\n />\n );\n }\n\n return (\n <span\n className={cn(\n \"inline-flex shrink-0 items-center justify-center rounded-sm border border-dashed border-muted-foreground/50 text-[0.65em] leading-none text-muted-foreground\",\n glyphClassName,\n )}\n title={title ?? name}\n role={title ? \"img\" : undefined}\n aria-label={title}\n aria-hidden={title ? undefined : true}\n style={{\n width: glyphWidth,\n height: glyphHeight,\n }}\n >\n ?\n </span>\n );\n}\n\nexport function Icon({\n icon: ImportedIcon,\n name,\n className,\n width,\n height,\n rotate,\n flip,\n inline,\n title,\n style = \"plain\",\n size,\n tone = \"neutral\",\n}: IconProps) {\n const density = useDensityValue();\n const pxSize = size != null ? resolveSize(size, density) : undefined;\n const glyphSize = pxSize != null ? Math.max(8, Math.round(pxSize * 0.5)) : undefined;\n const defaultGlyphSize = style === \"badge\" ? glyphSize : (pxSize ?? DEFAULT_PLAIN_ICON_SIZE);\n const resolvedWidth = width ?? height ?? defaultGlyphSize;\n const resolvedHeight = height ?? resolvedWidth;\n\n const glyphClassName = cn(\n \"inline-block shrink-0 align-[-0.125em]\",\n style === \"plain\" ? className : undefined,\n );\n const glyphTitle = style === \"plain\" ? title : undefined;\n\n const renderedIcon = ImportedIcon\n ? renderImportedGlyph(\n ImportedIcon,\n resolvedWidth,\n resolvedHeight,\n rotate,\n flip,\n inline,\n glyphClassName,\n glyphTitle,\n )\n : renderRuntimeGlyph(name, resolvedWidth, resolvedHeight, glyphClassName, glyphTitle);\n\n if (style === \"plain\") {\n return renderedIcon;\n }\n\n const badgeStyle: CSSProperties | undefined =\n pxSize != null ? { width: pxSize, height: pxSize } : undefined;\n\n return (\n <span\n title={title}\n aria-label={title}\n role={title ? \"img\" : undefined}\n className={cn(\n \"inline-flex items-center justify-center rounded-full bg-background shadow-sm ring-1 ring-inset\",\n TONE_CLASSES[tone],\n className,\n )}\n style={badgeStyle}\n >\n {renderedIcon}\n </span>\n );\n}\n\n/**\n * LabelIcon renders a label's leading glyph from a {@link LabelIconSpec}: a\n * string is treated as a runtime icon name (resolved by the registered fallback\n * provider), any other ReactNode is rendered as-is. Returns null for an absent\n * or empty spec so callers can spread it unconditionally before a label.\n */\nexport function LabelIcon({\n icon,\n className,\n}: {\n icon?: LabelIconSpec;\n className?: string;\n}): JSX.Element | null {\n if (icon == null || icon === \"\" || icon === false) return null;\n if (typeof icon === \"string\") {\n return <Icon name={icon} className={cn(\"shrink-0\", className)} />;\n }\n return <>{icon}</>;\n}\n"],"names":["jsx","cn","size","useDensityValue","resolveSize"],"mappings":"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"}
1
+ {"version":3,"file":"Icon.cjs","sources":["../../src/data/Icon.tsx"],"sourcesContent":["import type { CSSProperties, ElementType, ReactNode } from \"react\";\nimport { cn } from \"../lib/utils\";\nimport { resolveSize, type SizeToken } from \"../lib/size\";\nimport { useDensityValue } from \"../hooks/use-density\";\nimport { getFallbackIconProvider } from \"./icon-fallback\";\n\n// LabelIconSpec is the icon a label may carry: an iconify/runtime name (resolved\n// via the fallback provider) or a fully-rendered node the caller supplies.\nexport type LabelIconSpec = string | ReactNode;\n\nexport type IconStyle = \"plain\" | \"badge\";\n\nexport type IconTone = \"emerald\" | \"amber\" | \"rose\" | \"slate\" | \"sky\" | \"violet\" | \"neutral\";\n\nexport type StaticIconComponent = ElementType;\n\ntype CommonIconProps = {\n /** Classes applied to the glyph or badge wrapper. */\n className?: string;\n /** Explicit glyph width. */\n width?: string | number;\n /** Explicit glyph height. */\n height?: string | number;\n /** CSS rotate value or degrees. */\n rotate?: string | number;\n /** Flip direction for imported glyphs. */\n flip?: string;\n /** Forward inline rendering semantics to imported glyphs. */\n inline?: boolean;\n /** Accessible title for the glyph. */\n title?: string;\n /**\n * Presentation style. `plain` (default) renders the icon inline.\n * `badge` wraps the icon in a circular chip (white background, ring, shadow)\n * sized by `size` — use in stage/approval cells so the chip scales with a\n * neighbouring avatar.\n */\n style?: IconStyle;\n /**\n * Named size token (xxs..xxl). Drives the badge diameter and glyph. The\n * glyph is always ~50% of the badge diameter so it scales consistently\n * across sizes. For `style=\"plain\"` it sets width/height when neither is\n * provided.\n */\n size?: SizeToken;\n /** Semantic color for `style=\"badge\"`. Ignored for plain icons. */\n tone?: IconTone;\n};\n\nexport type IconProps = CommonIconProps &\n (\n | {\n /** Imported static icon component. */\n icon: StaticIconComponent;\n name?: never;\n }\n | {\n /** Runtime icon name resolved by the fallback provider. */\n name: string;\n icon?: never;\n }\n );\n\nconst TONE_CLASSES: Record<IconTone, string> = {\n emerald: \"text-emerald-700 ring-emerald-200/80 dark:text-emerald-400 dark:ring-emerald-500/30\",\n amber: \"text-amber-700 ring-amber-200/80 dark:text-amber-400 dark:ring-amber-500/30\",\n rose: \"text-rose-700 ring-rose-200/80 dark:text-rose-400 dark:ring-rose-500/30\",\n slate: \"text-slate-700 ring-slate-200/80 dark:text-slate-300 dark:ring-slate-500/30\",\n sky: \"text-sky-700 ring-sky-200/80 dark:text-sky-400 dark:ring-sky-500/30\",\n violet: \"text-violet-700 ring-violet-200/80 dark:text-violet-400 dark:ring-violet-500/30\",\n neutral: \"text-foreground ring-border\",\n};\n\nconst DEFAULT_PLAIN_ICON_SIZE = \"1em\";\n\nfunction renderImportedGlyph(\n ImportedIcon: StaticIconComponent,\n glyphWidth: number | string | undefined,\n glyphHeight: number | string | undefined,\n rotate: string | number | undefined,\n flip: string | undefined,\n inline: boolean | undefined,\n glyphClassName: string | undefined,\n title: string | undefined,\n): JSX.Element {\n const transform = [\n typeof rotate === \"number\" ? `rotate(${rotate}deg)` : typeof rotate === \"string\" ? rotate : \"\",\n flip === \"horizontal\" || flip === \"both\" ? \"scaleX(-1)\" : \"\",\n flip === \"vertical\" || flip === \"both\" ? \"scaleY(-1)\" : \"\",\n ]\n .filter(Boolean)\n .join(\" \");\n\n return (\n <ImportedIcon\n {...(glyphClassName ? { className: glyphClassName } : {})}\n {...(glyphWidth != null ? { width: glyphWidth } : {})}\n {...(glyphHeight != null ? { height: glyphHeight } : {})}\n {...(inline != null ? { \"aria-hidden\": !title } : {})}\n {...(title ? { title, role: \"img\" } : { \"aria-hidden\": true })}\n {...(transform ? { style: { transform } } : {})}\n />\n );\n}\n\nfunction renderRuntimeGlyph(\n name: string,\n glyphWidth: number | string | undefined,\n glyphHeight: number | string | undefined,\n glyphClassName: string | undefined,\n title: string | undefined,\n): JSX.Element {\n const fallbackIcon = getFallbackIconProvider();\n if (fallbackIcon) {\n const Fallback = fallbackIcon;\n const glyphSize = typeof glyphWidth === \"number\" ? glyphWidth : glyphHeight;\n return (\n <Fallback\n name={name}\n {...(glyphClassName ? { className: glyphClassName } : {})}\n {...(glyphSize != null ? { size: glyphSize } : {})}\n {...(title ? { alt: title } : {})}\n />\n );\n }\n\n return (\n <span\n className={cn(\n \"inline-flex shrink-0 items-center justify-center rounded-sm border border-dashed border-muted-foreground/50 text-[0.65em] leading-none text-muted-foreground\",\n glyphClassName,\n )}\n title={title ?? name}\n role={title ? \"img\" : undefined}\n aria-label={title}\n aria-hidden={title ? undefined : true}\n style={{\n width: glyphWidth,\n height: glyphHeight,\n }}\n >\n ?\n </span>\n );\n}\n\nexport function Icon({\n icon: ImportedIcon,\n name,\n className,\n width,\n height,\n rotate,\n flip,\n inline,\n title,\n style = \"plain\",\n size,\n tone = \"neutral\",\n}: IconProps) {\n const density = useDensityValue();\n const pxSize = size != null ? resolveSize(size, density) : undefined;\n const glyphSize = pxSize != null ? Math.max(8, Math.round(pxSize * 0.5)) : undefined;\n const defaultGlyphSize = style === \"badge\" ? glyphSize : (pxSize ?? DEFAULT_PLAIN_ICON_SIZE);\n const resolvedWidth = width ?? height ?? defaultGlyphSize;\n const resolvedHeight = height ?? resolvedWidth;\n\n const glyphClassName = cn(\n \"inline-block shrink-0 align-[-0.125em]\",\n style === \"plain\" ? className : undefined,\n );\n const glyphTitle = style === \"plain\" ? title : undefined;\n\n const renderedIcon = ImportedIcon\n ? renderImportedGlyph(\n ImportedIcon,\n resolvedWidth,\n resolvedHeight,\n rotate,\n flip,\n inline,\n glyphClassName,\n glyphTitle,\n )\n : renderRuntimeGlyph(name, resolvedWidth, resolvedHeight, glyphClassName, glyphTitle);\n\n if (style === \"plain\") {\n return renderedIcon;\n }\n\n const badgeStyle: CSSProperties | undefined =\n pxSize != null ? { width: pxSize, height: pxSize } : undefined;\n\n return (\n <span\n title={title}\n aria-label={title}\n role={title ? \"img\" : undefined}\n className={cn(\n \"inline-flex items-center justify-center rounded-full bg-background shadow-sm ring-1 ring-inset\",\n TONE_CLASSES[tone],\n className,\n )}\n style={badgeStyle}\n >\n {renderedIcon}\n </span>\n );\n}\n\n/**\n * LabelIcon renders a label's leading glyph from a {@link LabelIconSpec}: a\n * string is treated as a runtime icon name (resolved by the registered fallback\n * provider), any other ReactNode is rendered as-is. Returns null for an absent\n * or empty spec so callers can spread it unconditionally before a label.\n */\nexport function LabelIcon({\n icon,\n className,\n}: {\n icon?: LabelIconSpec;\n className?: string;\n}): JSX.Element | null {\n if (icon == null || icon === \"\" || icon === false) return null;\n if (typeof icon === \"string\") {\n return <Icon name={icon} className={cn(\"shrink-0\", className)} />;\n }\n return <>{icon}</>;\n}\n"],"names":["jsx","getFallbackIconProvider","cn","size","useDensityValue","resolveSize"],"mappings":";;;;;;;AA+DA,MAAM,eAAyC;AAAA,EAC7C,SAAS;AAAA,EACT,OAAO;AAAA,EACP,MAAM;AAAA,EACN,OAAO;AAAA,EACP,KAAK;AAAA,EACL,QAAQ;AAAA,EACR,SAAS;AACX;AAEA,MAAM,0BAA0B;AAEhC,SAAS,oBACP,cACA,YACA,aACA,QACA,MACA,QACA,gBACA,OACa;AACb,QAAM,YAAY;AAAA,IAChB,OAAO,WAAW,WAAW,UAAU,MAAM,SAAS,OAAO,WAAW,WAAW,SAAS;AAAA,IAC5F,SAAS,gBAAgB,SAAS,SAAS,eAAe;AAAA,IAC1D,SAAS,cAAc,SAAS,SAAS,eAAe;AAAA,EAAA,EAEvD,OAAO,OAAO,EACd,KAAK,GAAG;AAEX,SACEA,2BAAAA;AAAAA,IAAC;AAAA,IAAA;AAAA,MACE,GAAI,iBAAiB,EAAE,WAAW,eAAA,IAAmB,CAAA;AAAA,MACrD,GAAI,cAAc,OAAO,EAAE,OAAO,WAAA,IAAe,CAAA;AAAA,MACjD,GAAI,eAAe,OAAO,EAAE,QAAQ,YAAA,IAAgB,CAAA;AAAA,MACpD,GAAI,UAAU,OAAO,EAAE,eAAe,CAAC,MAAA,IAAU,CAAA;AAAA,MACjD,GAAI,QAAQ,EAAE,OAAO,MAAM,UAAU,EAAE,eAAe,KAAA;AAAA,MACtD,GAAI,YAAY,EAAE,OAAO,EAAE,UAAA,EAAU,IAAM,CAAA;AAAA,IAAC;AAAA,EAAA;AAGnD;AAEA,SAAS,mBACP,MACA,YACA,aACA,gBACA,OACa;AACb,QAAM,eAAeC,aAAAA,wBAAA;AACrB,MAAI,cAAc;AAChB,UAAM,WAAW;AACjB,UAAM,YAAY,OAAO,eAAe,WAAW,aAAa;AAChE,WACED,2BAAAA;AAAAA,MAAC;AAAA,MAAA;AAAA,QACC;AAAA,QACC,GAAI,iBAAiB,EAAE,WAAW,eAAA,IAAmB,CAAA;AAAA,QACrD,GAAI,aAAa,OAAO,EAAE,MAAM,UAAA,IAAc,CAAA;AAAA,QAC9C,GAAI,QAAQ,EAAE,KAAK,UAAU,CAAA;AAAA,MAAC;AAAA,IAAA;AAAA,EAGrC;AAEA,SACEA,2BAAAA;AAAAA,IAAC;AAAA,IAAA;AAAA,MACC,WAAWE,MAAAA;AAAAA,QACT;AAAA,QACA;AAAA,MAAA;AAAA,MAEF,OAAO,SAAS;AAAA,MAChB,MAAM,QAAQ,QAAQ;AAAA,MACtB,cAAY;AAAA,MACZ,eAAa,QAAQ,SAAY;AAAA,MACjC,OAAO;AAAA,QACL,OAAO;AAAA,QACP,QAAQ;AAAA,MAAA;AAAA,MAEX,UAAA;AAAA,IAAA;AAAA,EAAA;AAIL;AAEO,SAAS,KAAK;AAAA,EACnB,MAAM;AAAA,EACN;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,QAAQ;AAAA,EAAA,MACRC;AAAAA,EACA,OAAO;AACT,GAAc;AACZ,QAAM,UAAUC,WAAAA,gBAAA;AAChB,QAAM,SAASD,UAAQ,OAAOE,KAAAA,YAAYF,QAAM,OAAO,IAAI;AAC3D,QAAM,YAAY,UAAU,OAAO,KAAK,IAAI,GAAG,KAAK,MAAM,SAAS,GAAG,CAAC,IAAI;AAC3E,QAAM,mBAAmB,UAAU,UAAU,YAAa,UAAU;AACpE,QAAM,gBAAgB,SAAS,UAAU;AACzC,QAAM,iBAAiB,UAAU;AAEjC,QAAM,iBAAiBD,MAAAA;AAAAA,IACrB;AAAA,IACA,UAAU,UAAU,YAAY;AAAA,EAAA;AAElC,QAAM,aAAa,UAAU,UAAU,QAAQ;AAE/C,QAAM,eAAe,eACjB;AAAA,IACE;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EAAA,IAEF,mBAAmB,MAAM,eAAe,gBAAgB,gBAAgB,UAAU;AAEtF,MAAI,UAAU,SAAS;AACrB,WAAO;AAAA,EACT;AAEA,QAAM,aACJ,UAAU,OAAO,EAAE,OAAO,QAAQ,QAAQ,WAAW;AAEvD,SACEF,2BAAAA;AAAAA,IAAC;AAAA,IAAA;AAAA,MACC;AAAA,MACA,cAAY;AAAA,MACZ,MAAM,QAAQ,QAAQ;AAAA,MACtB,WAAWE,MAAAA;AAAAA,QACT;AAAA,QACA,aAAa,IAAI;AAAA,QACjB;AAAA,MAAA;AAAA,MAEF,OAAO;AAAA,MAEN,UAAA;AAAA,IAAA;AAAA,EAAA;AAGP;AAQO,SAAS,UAAU;AAAA,EACxB;AAAA,EACA;AACF,GAGuB;AACrB,MAAI,QAAQ,QAAQ,SAAS,MAAM,SAAS,MAAO,QAAO;AAC1D,MAAI,OAAO,SAAS,UAAU;AAC5B,WAAOF,2BAAAA,IAAC,QAAK,MAAM,MAAM,WAAWE,SAAG,YAAY,SAAS,GAAG;AAAA,EACjE;AACA,+DAAU,UAAA,KAAA,CAAK;AACjB;;;"}
@@ -1,4 +1,4 @@
1
- import { ComponentType, ElementType, ReactNode } from 'react';
1
+ import { ElementType, ReactNode } from 'react';
2
2
  import { SizeToken } from '../lib/size';
3
3
  export type LabelIconSpec = string | ReactNode;
4
4
  export type IconStyle = "plain" | "badge";
@@ -45,26 +45,6 @@ export type IconProps = CommonIconProps & ({
45
45
  name: string;
46
46
  icon?: never;
47
47
  });
48
- /**
49
- * Optional secondary icon provider for user-supplied runtime names.
50
- * Built-in/default icons should pass an imported component via `icon`.
51
- */
52
- export type FallbackIconProps = {
53
- /** Runtime icon name to resolve. */
54
- name?: string;
55
- /** Classes applied by Icon. */
56
- className?: string;
57
- /** Requested glyph size. */
58
- size?: string | number;
59
- /** Accessible label. */
60
- alt?: string;
61
- };
62
- type FallbackIconComponent = ComponentType<FallbackIconProps>;
63
- /**
64
- * Register a secondary glyph provider. Pass the flanksource Icon/ResourceIcon
65
- * (or any compatible component) to resolve user-supplied runtime names.
66
- */
67
- export declare function setFallbackIconProvider(component: FallbackIconComponent | null): void;
68
48
  export declare function Icon({ icon: ImportedIcon, name, className, width, height, rotate, flip, inline, title, style, size, tone, }: IconProps): import("react/jsx-runtime").JSX.Element;
69
49
  /**
70
50
  * LabelIcon renders a label's leading glyph from a {@link LabelIconSpec}: a
@@ -1 +1 @@
1
- {"version":3,"file":"Icon.d.ts","sourceRoot":"","sources":["../../src/data/Icon.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAiB,aAAa,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAElF,OAAO,EAAe,KAAK,SAAS,EAAE,MAAM,aAAa,CAAC;AAK1D,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,SAAS,CAAC;AAE/C,MAAM,MAAM,SAAS,GAAG,OAAO,GAAG,OAAO,CAAC;AAE1C,MAAM,MAAM,QAAQ,GAAG,SAAS,GAAG,OAAO,GAAG,MAAM,GAAG,OAAO,GAAG,KAAK,GAAG,QAAQ,GAAG,SAAS,CAAC;AAE7F,MAAM,MAAM,mBAAmB,GAAG,WAAW,CAAC;AAE9C,KAAK,eAAe,GAAG;IACrB,qDAAqD;IACrD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,4BAA4B;IAC5B,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACxB,6BAA6B;IAC7B,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACzB,mCAAmC;IACnC,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACzB,0CAA0C;IAC1C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,6DAA6D;IAC7D,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,sCAAsC;IACtC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;;OAKG;IACH,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB;;;;;OAKG;IACH,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,mEAAmE;IACnE,IAAI,CAAC,EAAE,QAAQ,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,SAAS,GAAG,eAAe,GACrC,CACI;IACE,sCAAsC;IACtC,IAAI,EAAE,mBAAmB,CAAC;IAC1B,IAAI,CAAC,EAAE,KAAK,CAAC;CACd,GACD;IACE,2DAA2D;IAC3D,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,KAAK,CAAC;CACd,CACJ,CAAC;AAcJ;;;GAGG;AACH,MAAM,MAAM,iBAAiB,GAAG;IAC9B,oCAAoC;IACpC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,+BAA+B;IAC/B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,4BAA4B;IAC5B,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACvB,wBAAwB;IACxB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,KAAK,qBAAqB,GAAG,aAAa,CAAC,iBAAiB,CAAC,CAAC;AAI9D;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,SAAS,EAAE,qBAAqB,GAAG,IAAI,GAAG,IAAI,CAErF;AAwED,wBAAgB,IAAI,CAAC,EACnB,IAAI,EAAE,YAAY,EAClB,IAAI,EACJ,SAAS,EACT,KAAK,EACL,MAAM,EACN,MAAM,EACN,IAAI,EACJ,MAAM,EACN,KAAK,EACL,KAAe,EACf,IAAI,EACJ,IAAgB,GACjB,EAAE,SAAS,2CAiDX;AAED;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,EACxB,IAAI,EACJ,SAAS,GACV,EAAE;IACD,IAAI,CAAC,EAAE,aAAa,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,GAAG,GAAG,CAAC,OAAO,GAAG,IAAI,CAMrB"}
1
+ {"version":3,"file":"Icon.d.ts","sourceRoot":"","sources":["../../src/data/Icon.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAiB,WAAW,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEnE,OAAO,EAAe,KAAK,SAAS,EAAE,MAAM,aAAa,CAAC;AAM1D,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,SAAS,CAAC;AAE/C,MAAM,MAAM,SAAS,GAAG,OAAO,GAAG,OAAO,CAAC;AAE1C,MAAM,MAAM,QAAQ,GAAG,SAAS,GAAG,OAAO,GAAG,MAAM,GAAG,OAAO,GAAG,KAAK,GAAG,QAAQ,GAAG,SAAS,CAAC;AAE7F,MAAM,MAAM,mBAAmB,GAAG,WAAW,CAAC;AAE9C,KAAK,eAAe,GAAG;IACrB,qDAAqD;IACrD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,4BAA4B;IAC5B,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACxB,6BAA6B;IAC7B,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACzB,mCAAmC;IACnC,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACzB,0CAA0C;IAC1C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,6DAA6D;IAC7D,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,sCAAsC;IACtC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;;OAKG;IACH,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB;;;;;OAKG;IACH,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,mEAAmE;IACnE,IAAI,CAAC,EAAE,QAAQ,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,SAAS,GAAG,eAAe,GACrC,CACI;IACE,sCAAsC;IACtC,IAAI,EAAE,mBAAmB,CAAC;IAC1B,IAAI,CAAC,EAAE,KAAK,CAAC;CACd,GACD;IACE,2DAA2D;IAC3D,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,KAAK,CAAC;CACd,CACJ,CAAC;AAqFJ,wBAAgB,IAAI,CAAC,EACnB,IAAI,EAAE,YAAY,EAClB,IAAI,EACJ,SAAS,EACT,KAAK,EACL,MAAM,EACN,MAAM,EACN,IAAI,EACJ,MAAM,EACN,KAAK,EACL,KAAe,EACf,IAAI,EACJ,IAAgB,GACjB,EAAE,SAAS,2CAiDX;AAED;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,EACxB,IAAI,EACJ,SAAS,GACV,EAAE;IACD,IAAI,CAAC,EAAE,aAAa,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,GAAG,GAAG,CAAC,OAAO,GAAG,IAAI,CAMrB"}
package/dist/data/Icon.js CHANGED
@@ -2,6 +2,7 @@ import { jsx, Fragment } from "react/jsx-runtime";
2
2
  import { cn } from "../lib/utils.js";
3
3
  import { resolveSize } from "../lib/size.js";
4
4
  import { useDensityValue } from "../hooks/use-density.js";
5
+ import { getFallbackIconProvider } from "./icon-fallback.js";
5
6
  const TONE_CLASSES = {
6
7
  emerald: "text-emerald-700 ring-emerald-200/80 dark:text-emerald-400 dark:ring-emerald-500/30",
7
8
  amber: "text-amber-700 ring-amber-200/80 dark:text-amber-400 dark:ring-amber-500/30",
@@ -12,10 +13,6 @@ const TONE_CLASSES = {
12
13
  neutral: "text-foreground ring-border"
13
14
  };
14
15
  const DEFAULT_PLAIN_ICON_SIZE = "1em";
15
- let fallbackIcon = null;
16
- function setFallbackIconProvider(component) {
17
- fallbackIcon = component;
18
- }
19
16
  function renderImportedGlyph(ImportedIcon, glyphWidth, glyphHeight, rotate, flip, inline, glyphClassName, title) {
20
17
  const transform = [
21
18
  typeof rotate === "number" ? `rotate(${rotate}deg)` : typeof rotate === "string" ? rotate : "",
@@ -35,6 +32,7 @@ function renderImportedGlyph(ImportedIcon, glyphWidth, glyphHeight, rotate, flip
35
32
  );
36
33
  }
37
34
  function renderRuntimeGlyph(name, glyphWidth, glyphHeight, glyphClassName, title) {
35
+ const fallbackIcon = getFallbackIconProvider();
38
36
  if (fallbackIcon) {
39
37
  const Fallback = fallbackIcon;
40
38
  const glyphSize = typeof glyphWidth === "number" ? glyphWidth : glyphHeight;
@@ -134,7 +132,6 @@ function LabelIcon({
134
132
  }
135
133
  export {
136
134
  Icon,
137
- LabelIcon,
138
- setFallbackIconProvider
135
+ LabelIcon
139
136
  };
140
137
  //# sourceMappingURL=Icon.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Icon.js","sources":["../../src/data/Icon.tsx"],"sourcesContent":["import type { CSSProperties, ComponentType, ElementType, ReactNode } from \"react\";\nimport { cn } from \"../lib/utils\";\nimport { resolveSize, type SizeToken } from \"../lib/size\";\nimport { useDensityValue } from \"../hooks/use-density\";\n\n// LabelIconSpec is the icon a label may carry: an iconify/runtime name (resolved\n// via the fallback provider) or a fully-rendered node the caller supplies.\nexport type LabelIconSpec = string | ReactNode;\n\nexport type IconStyle = \"plain\" | \"badge\";\n\nexport type IconTone = \"emerald\" | \"amber\" | \"rose\" | \"slate\" | \"sky\" | \"violet\" | \"neutral\";\n\nexport type StaticIconComponent = ElementType;\n\ntype CommonIconProps = {\n /** Classes applied to the glyph or badge wrapper. */\n className?: string;\n /** Explicit glyph width. */\n width?: string | number;\n /** Explicit glyph height. */\n height?: string | number;\n /** CSS rotate value or degrees. */\n rotate?: string | number;\n /** Flip direction for imported glyphs. */\n flip?: string;\n /** Forward inline rendering semantics to imported glyphs. */\n inline?: boolean;\n /** Accessible title for the glyph. */\n title?: string;\n /**\n * Presentation style. `plain` (default) renders the icon inline.\n * `badge` wraps the icon in a circular chip (white background, ring, shadow)\n * sized by `size` — use in stage/approval cells so the chip scales with a\n * neighbouring avatar.\n */\n style?: IconStyle;\n /**\n * Named size token (xxs..xxl). Drives the badge diameter and glyph. The\n * glyph is always ~50% of the badge diameter so it scales consistently\n * across sizes. For `style=\"plain\"` it sets width/height when neither is\n * provided.\n */\n size?: SizeToken;\n /** Semantic color for `style=\"badge\"`. Ignored for plain icons. */\n tone?: IconTone;\n};\n\nexport type IconProps = CommonIconProps &\n (\n | {\n /** Imported static icon component. */\n icon: StaticIconComponent;\n name?: never;\n }\n | {\n /** Runtime icon name resolved by the fallback provider. */\n name: string;\n icon?: never;\n }\n );\n\nconst TONE_CLASSES: Record<IconTone, string> = {\n emerald: \"text-emerald-700 ring-emerald-200/80 dark:text-emerald-400 dark:ring-emerald-500/30\",\n amber: \"text-amber-700 ring-amber-200/80 dark:text-amber-400 dark:ring-amber-500/30\",\n rose: \"text-rose-700 ring-rose-200/80 dark:text-rose-400 dark:ring-rose-500/30\",\n slate: \"text-slate-700 ring-slate-200/80 dark:text-slate-300 dark:ring-slate-500/30\",\n sky: \"text-sky-700 ring-sky-200/80 dark:text-sky-400 dark:ring-sky-500/30\",\n violet: \"text-violet-700 ring-violet-200/80 dark:text-violet-400 dark:ring-violet-500/30\",\n neutral: \"text-foreground ring-border\",\n};\n\nconst DEFAULT_PLAIN_ICON_SIZE = \"1em\";\n\n/**\n * Optional secondary icon provider for user-supplied runtime names.\n * Built-in/default icons should pass an imported component via `icon`.\n */\nexport type FallbackIconProps = {\n /** Runtime icon name to resolve. */\n name?: string;\n /** Classes applied by Icon. */\n className?: string;\n /** Requested glyph size. */\n size?: string | number;\n /** Accessible label. */\n alt?: string;\n};\n\ntype FallbackIconComponent = ComponentType<FallbackIconProps>;\n\nlet fallbackIcon: FallbackIconComponent | null = null;\n\n/**\n * Register a secondary glyph provider. Pass the flanksource Icon/ResourceIcon\n * (or any compatible component) to resolve user-supplied runtime names.\n */\nexport function setFallbackIconProvider(component: FallbackIconComponent | null): void {\n fallbackIcon = component;\n}\n\nfunction renderImportedGlyph(\n ImportedIcon: StaticIconComponent,\n glyphWidth: number | string | undefined,\n glyphHeight: number | string | undefined,\n rotate: string | number | undefined,\n flip: string | undefined,\n inline: boolean | undefined,\n glyphClassName: string | undefined,\n title: string | undefined,\n): JSX.Element {\n const transform = [\n typeof rotate === \"number\" ? `rotate(${rotate}deg)` : typeof rotate === \"string\" ? rotate : \"\",\n flip === \"horizontal\" || flip === \"both\" ? \"scaleX(-1)\" : \"\",\n flip === \"vertical\" || flip === \"both\" ? \"scaleY(-1)\" : \"\",\n ]\n .filter(Boolean)\n .join(\" \");\n\n return (\n <ImportedIcon\n {...(glyphClassName ? { className: glyphClassName } : {})}\n {...(glyphWidth != null ? { width: glyphWidth } : {})}\n {...(glyphHeight != null ? { height: glyphHeight } : {})}\n {...(inline != null ? { \"aria-hidden\": !title } : {})}\n {...(title ? { title, role: \"img\" } : { \"aria-hidden\": true })}\n {...(transform ? { style: { transform } } : {})}\n />\n );\n}\n\nfunction renderRuntimeGlyph(\n name: string,\n glyphWidth: number | string | undefined,\n glyphHeight: number | string | undefined,\n glyphClassName: string | undefined,\n title: string | undefined,\n): JSX.Element {\n if (fallbackIcon) {\n const Fallback = fallbackIcon;\n const glyphSize = typeof glyphWidth === \"number\" ? glyphWidth : glyphHeight;\n return (\n <Fallback\n name={name}\n {...(glyphClassName ? { className: glyphClassName } : {})}\n {...(glyphSize != null ? { size: glyphSize } : {})}\n {...(title ? { alt: title } : {})}\n />\n );\n }\n\n return (\n <span\n className={cn(\n \"inline-flex shrink-0 items-center justify-center rounded-sm border border-dashed border-muted-foreground/50 text-[0.65em] leading-none text-muted-foreground\",\n glyphClassName,\n )}\n title={title ?? name}\n role={title ? \"img\" : undefined}\n aria-label={title}\n aria-hidden={title ? undefined : true}\n style={{\n width: glyphWidth,\n height: glyphHeight,\n }}\n >\n ?\n </span>\n );\n}\n\nexport function Icon({\n icon: ImportedIcon,\n name,\n className,\n width,\n height,\n rotate,\n flip,\n inline,\n title,\n style = \"plain\",\n size,\n tone = \"neutral\",\n}: IconProps) {\n const density = useDensityValue();\n const pxSize = size != null ? resolveSize(size, density) : undefined;\n const glyphSize = pxSize != null ? Math.max(8, Math.round(pxSize * 0.5)) : undefined;\n const defaultGlyphSize = style === \"badge\" ? glyphSize : (pxSize ?? DEFAULT_PLAIN_ICON_SIZE);\n const resolvedWidth = width ?? height ?? defaultGlyphSize;\n const resolvedHeight = height ?? resolvedWidth;\n\n const glyphClassName = cn(\n \"inline-block shrink-0 align-[-0.125em]\",\n style === \"plain\" ? className : undefined,\n );\n const glyphTitle = style === \"plain\" ? title : undefined;\n\n const renderedIcon = ImportedIcon\n ? renderImportedGlyph(\n ImportedIcon,\n resolvedWidth,\n resolvedHeight,\n rotate,\n flip,\n inline,\n glyphClassName,\n glyphTitle,\n )\n : renderRuntimeGlyph(name, resolvedWidth, resolvedHeight, glyphClassName, glyphTitle);\n\n if (style === \"plain\") {\n return renderedIcon;\n }\n\n const badgeStyle: CSSProperties | undefined =\n pxSize != null ? { width: pxSize, height: pxSize } : undefined;\n\n return (\n <span\n title={title}\n aria-label={title}\n role={title ? \"img\" : undefined}\n className={cn(\n \"inline-flex items-center justify-center rounded-full bg-background shadow-sm ring-1 ring-inset\",\n TONE_CLASSES[tone],\n className,\n )}\n style={badgeStyle}\n >\n {renderedIcon}\n </span>\n );\n}\n\n/**\n * LabelIcon renders a label's leading glyph from a {@link LabelIconSpec}: a\n * string is treated as a runtime icon name (resolved by the registered fallback\n * provider), any other ReactNode is rendered as-is. Returns null for an absent\n * or empty spec so callers can spread it unconditionally before a label.\n */\nexport function LabelIcon({\n icon,\n className,\n}: {\n icon?: LabelIconSpec;\n className?: string;\n}): JSX.Element | null {\n if (icon == null || icon === \"\" || icon === false) return null;\n if (typeof icon === \"string\") {\n return <Icon name={icon} className={cn(\"shrink-0\", className)} />;\n }\n return <>{icon}</>;\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Icon.js","sources":["../../src/data/Icon.tsx"],"sourcesContent":["import type { CSSProperties, ElementType, ReactNode } from \"react\";\nimport { cn } from \"../lib/utils\";\nimport { resolveSize, type SizeToken } from \"../lib/size\";\nimport { useDensityValue } from \"../hooks/use-density\";\nimport { getFallbackIconProvider } from \"./icon-fallback\";\n\n// LabelIconSpec is the icon a label may carry: an iconify/runtime name (resolved\n// via the fallback provider) or a fully-rendered node the caller supplies.\nexport type LabelIconSpec = string | ReactNode;\n\nexport type IconStyle = \"plain\" | \"badge\";\n\nexport type IconTone = \"emerald\" | \"amber\" | \"rose\" | \"slate\" | \"sky\" | \"violet\" | \"neutral\";\n\nexport type StaticIconComponent = ElementType;\n\ntype CommonIconProps = {\n /** Classes applied to the glyph or badge wrapper. */\n className?: string;\n /** Explicit glyph width. */\n width?: string | number;\n /** Explicit glyph height. */\n height?: string | number;\n /** CSS rotate value or degrees. */\n rotate?: string | number;\n /** Flip direction for imported glyphs. */\n flip?: string;\n /** Forward inline rendering semantics to imported glyphs. */\n inline?: boolean;\n /** Accessible title for the glyph. */\n title?: string;\n /**\n * Presentation style. `plain` (default) renders the icon inline.\n * `badge` wraps the icon in a circular chip (white background, ring, shadow)\n * sized by `size` — use in stage/approval cells so the chip scales with a\n * neighbouring avatar.\n */\n style?: IconStyle;\n /**\n * Named size token (xxs..xxl). Drives the badge diameter and glyph. The\n * glyph is always ~50% of the badge diameter so it scales consistently\n * across sizes. For `style=\"plain\"` it sets width/height when neither is\n * provided.\n */\n size?: SizeToken;\n /** Semantic color for `style=\"badge\"`. Ignored for plain icons. */\n tone?: IconTone;\n};\n\nexport type IconProps = CommonIconProps &\n (\n | {\n /** Imported static icon component. */\n icon: StaticIconComponent;\n name?: never;\n }\n | {\n /** Runtime icon name resolved by the fallback provider. */\n name: string;\n icon?: never;\n }\n );\n\nconst TONE_CLASSES: Record<IconTone, string> = {\n emerald: \"text-emerald-700 ring-emerald-200/80 dark:text-emerald-400 dark:ring-emerald-500/30\",\n amber: \"text-amber-700 ring-amber-200/80 dark:text-amber-400 dark:ring-amber-500/30\",\n rose: \"text-rose-700 ring-rose-200/80 dark:text-rose-400 dark:ring-rose-500/30\",\n slate: \"text-slate-700 ring-slate-200/80 dark:text-slate-300 dark:ring-slate-500/30\",\n sky: \"text-sky-700 ring-sky-200/80 dark:text-sky-400 dark:ring-sky-500/30\",\n violet: \"text-violet-700 ring-violet-200/80 dark:text-violet-400 dark:ring-violet-500/30\",\n neutral: \"text-foreground ring-border\",\n};\n\nconst DEFAULT_PLAIN_ICON_SIZE = \"1em\";\n\nfunction renderImportedGlyph(\n ImportedIcon: StaticIconComponent,\n glyphWidth: number | string | undefined,\n glyphHeight: number | string | undefined,\n rotate: string | number | undefined,\n flip: string | undefined,\n inline: boolean | undefined,\n glyphClassName: string | undefined,\n title: string | undefined,\n): JSX.Element {\n const transform = [\n typeof rotate === \"number\" ? `rotate(${rotate}deg)` : typeof rotate === \"string\" ? rotate : \"\",\n flip === \"horizontal\" || flip === \"both\" ? \"scaleX(-1)\" : \"\",\n flip === \"vertical\" || flip === \"both\" ? \"scaleY(-1)\" : \"\",\n ]\n .filter(Boolean)\n .join(\" \");\n\n return (\n <ImportedIcon\n {...(glyphClassName ? { className: glyphClassName } : {})}\n {...(glyphWidth != null ? { width: glyphWidth } : {})}\n {...(glyphHeight != null ? { height: glyphHeight } : {})}\n {...(inline != null ? { \"aria-hidden\": !title } : {})}\n {...(title ? { title, role: \"img\" } : { \"aria-hidden\": true })}\n {...(transform ? { style: { transform } } : {})}\n />\n );\n}\n\nfunction renderRuntimeGlyph(\n name: string,\n glyphWidth: number | string | undefined,\n glyphHeight: number | string | undefined,\n glyphClassName: string | undefined,\n title: string | undefined,\n): JSX.Element {\n const fallbackIcon = getFallbackIconProvider();\n if (fallbackIcon) {\n const Fallback = fallbackIcon;\n const glyphSize = typeof glyphWidth === \"number\" ? glyphWidth : glyphHeight;\n return (\n <Fallback\n name={name}\n {...(glyphClassName ? { className: glyphClassName } : {})}\n {...(glyphSize != null ? { size: glyphSize } : {})}\n {...(title ? { alt: title } : {})}\n />\n );\n }\n\n return (\n <span\n className={cn(\n \"inline-flex shrink-0 items-center justify-center rounded-sm border border-dashed border-muted-foreground/50 text-[0.65em] leading-none text-muted-foreground\",\n glyphClassName,\n )}\n title={title ?? name}\n role={title ? \"img\" : undefined}\n aria-label={title}\n aria-hidden={title ? undefined : true}\n style={{\n width: glyphWidth,\n height: glyphHeight,\n }}\n >\n ?\n </span>\n );\n}\n\nexport function Icon({\n icon: ImportedIcon,\n name,\n className,\n width,\n height,\n rotate,\n flip,\n inline,\n title,\n style = \"plain\",\n size,\n tone = \"neutral\",\n}: IconProps) {\n const density = useDensityValue();\n const pxSize = size != null ? resolveSize(size, density) : undefined;\n const glyphSize = pxSize != null ? Math.max(8, Math.round(pxSize * 0.5)) : undefined;\n const defaultGlyphSize = style === \"badge\" ? glyphSize : (pxSize ?? DEFAULT_PLAIN_ICON_SIZE);\n const resolvedWidth = width ?? height ?? defaultGlyphSize;\n const resolvedHeight = height ?? resolvedWidth;\n\n const glyphClassName = cn(\n \"inline-block shrink-0 align-[-0.125em]\",\n style === \"plain\" ? className : undefined,\n );\n const glyphTitle = style === \"plain\" ? title : undefined;\n\n const renderedIcon = ImportedIcon\n ? renderImportedGlyph(\n ImportedIcon,\n resolvedWidth,\n resolvedHeight,\n rotate,\n flip,\n inline,\n glyphClassName,\n glyphTitle,\n )\n : renderRuntimeGlyph(name, resolvedWidth, resolvedHeight, glyphClassName, glyphTitle);\n\n if (style === \"plain\") {\n return renderedIcon;\n }\n\n const badgeStyle: CSSProperties | undefined =\n pxSize != null ? { width: pxSize, height: pxSize } : undefined;\n\n return (\n <span\n title={title}\n aria-label={title}\n role={title ? \"img\" : undefined}\n className={cn(\n \"inline-flex items-center justify-center rounded-full bg-background shadow-sm ring-1 ring-inset\",\n TONE_CLASSES[tone],\n className,\n )}\n style={badgeStyle}\n >\n {renderedIcon}\n </span>\n );\n}\n\n/**\n * LabelIcon renders a label's leading glyph from a {@link LabelIconSpec}: a\n * string is treated as a runtime icon name (resolved by the registered fallback\n * provider), any other ReactNode is rendered as-is. Returns null for an absent\n * or empty spec so callers can spread it unconditionally before a label.\n */\nexport function LabelIcon({\n icon,\n className,\n}: {\n icon?: LabelIconSpec;\n className?: string;\n}): JSX.Element | null {\n if (icon == null || icon === \"\" || icon === false) return null;\n if (typeof icon === \"string\") {\n return <Icon name={icon} className={cn(\"shrink-0\", className)} />;\n }\n return <>{icon}</>;\n}\n"],"names":[],"mappings":"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"}
@@ -40,13 +40,13 @@ function MatrixTable({
40
40
  /* @__PURE__ */ jsxRuntime.jsx("col", {}),
41
41
  columns.map((_, index) => /* @__PURE__ */ jsxRuntime.jsx("col", { style: { width: columnWidth } }, index))
42
42
  ] }),
43
- /* @__PURE__ */ jsxRuntime.jsx("thead", { children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { className: utils.cn("bg-muted/40", !angledHeaders && "border-b border-border", headerClassName), children: [
43
+ /* @__PURE__ */ jsxRuntime.jsx("thead", { children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { className: utils.cn(!angledHeaders && "border-b border-border", headerClassName), children: [
44
44
  /* @__PURE__ */ jsxRuntime.jsx(
45
45
  "th",
46
46
  {
47
47
  scope: "col",
48
48
  className: utils.cn(
49
- "sticky left-0 top-0 z-30 min-w-44 border-r border-border bg-muted text-left font-medium",
49
+ "sticky left-0 top-0 z-30 min-w-44 border-r border-border text-left font-medium",
50
50
  headerCellPadding,
51
51
  angledHeaders ? "align-bottom" : utils.cn("border-b border-border", columnClassName),
52
52
  headerClassName
@@ -61,7 +61,7 @@ function MatrixTable({
61
61
  scope: "col",
62
62
  title: columnTitle(column),
63
63
  className: utils.cn(
64
- "sticky top-0 z-20 overflow-visible border-b border-border bg-muted p-0 align-bottom",
64
+ "sticky top-0 z-20 overflow-visible border-b border-border p-0 align-bottom",
65
65
  columnClassName,
66
66
  headerClassName
67
67
  ),
@@ -117,7 +117,7 @@ function MatrixTable({
117
117
  {
118
118
  scope: "col",
119
119
  className: utils.cn(
120
- "sticky top-0 z-20 min-w-24 whitespace-nowrap border-b border-border bg-muted text-center text-xs font-medium text-muted-foreground",
120
+ "sticky top-0 z-20 min-w-24 whitespace-nowrap border-b border-border text-center text-xs font-medium text-muted-foreground",
121
121
  headerCellPadding,
122
122
  columnClassName,
123
123
  headerClassName
@@ -1 +1 @@
1
- {"version":3,"file":"MatrixTable.cjs","sources":["../../src/data/MatrixTable.tsx"],"sourcesContent":["import type { ReactNode } from \"react\";\nimport { cn } from \"../lib/utils\";\n\nexport type MatrixTableRow = {\n key: string;\n label: ReactNode;\n cells: ReactNode[];\n};\n\nexport type MatrixTableProps = {\n columns: ReactNode[];\n rows: MatrixTableRow[];\n corner?: ReactNode;\n emptyMessage?: ReactNode;\n angledHeaders?: boolean;\n density?: \"default\" | \"compact\";\n columnWidth?: number;\n headerHeight?: number;\n // maxHeight caps the scroll viewport so the body scrolls under frozen\n // headers (Excel-style freeze panes). Accepts any CSS length; number => px.\n maxHeight?: number | string;\n className?: string;\n columnClassName?: string;\n rowLabelClassName?: string;\n cellClassName?: string;\n // headerClassName is appended to the header row and every header cell (corner\n // + columns). Use it to override the default gray header background, e.g.\n // \"bg-transparent\", since tailwind-merge lets the later class win.\n headerClassName?: string;\n};\n\nexport function MatrixTable({\n columns,\n rows,\n corner,\n emptyMessage = \"No data\",\n angledHeaders = false,\n density = \"default\",\n columnWidth = 48,\n headerHeight = 120,\n maxHeight,\n className,\n columnClassName,\n rowLabelClassName,\n cellClassName,\n headerClassName,\n}: MatrixTableProps) {\n if (rows.length === 0 || columns.length === 0) {\n return <div className=\"text-sm text-muted-foreground\">{emptyMessage}</div>;\n }\n\n const textWidth = Math.round(headerHeight * 1.41);\n const diagonalOverhang = Math.round(headerHeight * 0.71);\n const compact = density === \"compact\";\n const headerCellPadding = compact ? \"px-density-2 py-density-1\" : \"px-density-3 py-density-2\";\n const rowLabelPadding = compact ? \"px-density-2 py-1\" : \"px-density-3 py-density-2\";\n const bodyCellPadding = compact ? \"px-density-2 py-1\" : \"px-density-3 py-density-2\";\n\n return (\n <div\n className={cn(\"overflow-auto rounded-md border border-border\", className)}\n style={{\n ...(angledHeaders ? { paddingRight: diagonalOverhang } : undefined),\n ...(maxHeight !== undefined ? { maxHeight } : undefined),\n }}\n >\n <table className={cn(\"w-max border-collapse\", compact ? \"text-xs\" : \"text-sm\")}>\n {angledHeaders && (\n <colgroup>\n <col />\n {columns.map((_, index) => (\n <col key={index} style={{ width: columnWidth }} />\n ))}\n </colgroup>\n )}\n <thead>\n <tr className={cn(\"bg-muted/40\", !angledHeaders && \"border-b border-border\", headerClassName)}>\n <th\n scope=\"col\"\n className={cn(\n \"sticky left-0 top-0 z-30 min-w-44 border-r border-border bg-muted text-left font-medium\",\n headerCellPadding,\n angledHeaders ? \"align-bottom\" : cn(\"border-b border-border\", columnClassName),\n headerClassName,\n )}\n >\n {corner}\n </th>\n {columns.map((column, index) =>\n angledHeaders ? (\n <th\n key={index}\n scope=\"col\"\n title={columnTitle(column)}\n className={cn(\n \"sticky top-0 z-20 overflow-visible border-b border-border bg-muted p-0 align-bottom\",\n columnClassName,\n headerClassName,\n )}\n style={{\n width: columnWidth,\n minWidth: columnWidth,\n maxWidth: columnWidth,\n height: headerHeight,\n }}\n >\n <div\n className=\"absolute bottom-0 border-b border-border\"\n style={{\n left: columnWidth,\n width: textWidth,\n transform: \"rotate(-45deg)\",\n transformOrigin: \"0 100%\",\n }}\n />\n {index === 0 && (\n <div\n className=\"absolute bottom-0 border-b border-border\"\n style={{\n left: 0,\n width: textWidth,\n transform: \"rotate(-45deg)\",\n transformOrigin: \"0 100%\",\n }}\n />\n )}\n <div\n className=\"absolute bottom-2 overflow-hidden text-ellipsis whitespace-nowrap pl-1 text-left text-xs font-medium leading-none text-muted-foreground\"\n style={{\n left: columnWidth / 2,\n width: textWidth,\n transform: \"rotate(-45deg)\",\n transformOrigin: \"0 100%\",\n }}\n >\n {column}\n </div>\n </th>\n ) : (\n <th\n key={index}\n scope=\"col\"\n className={cn(\n \"sticky top-0 z-20 min-w-24 whitespace-nowrap border-b border-border bg-muted text-center text-xs font-medium text-muted-foreground\",\n headerCellPadding,\n columnClassName,\n headerClassName,\n )}\n >\n {column}\n </th>\n ),\n )}\n </tr>\n </thead>\n <tbody>\n {rows.map((row) => (\n <tr key={row.key} className=\"border-b border-border last:border-b-0\">\n <th\n scope=\"row\"\n className={cn(\n \"sticky left-0 z-10 border-r border-border bg-background text-left font-medium\",\n rowLabelPadding,\n rowLabelClassName,\n )}\n >\n {row.label}\n </th>\n {columns.map((_, index) => (\n <td\n key={index}\n className={cn(\n angledHeaders\n ? \"p-0 text-center align-middle\"\n : cn(bodyCellPadding, \"text-center align-middle\"),\n cellClassName,\n )}\n style={\n angledHeaders\n ? {\n width: columnWidth,\n minWidth: columnWidth,\n maxWidth: columnWidth,\n }\n : undefined\n }\n >\n {row.cells[index] ?? null}\n </td>\n ))}\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n );\n}\n\nfunction columnTitle(column: ReactNode) {\n if (typeof column === \"string\" || typeof column === \"number\") {\n return String(column);\n }\n return undefined;\n}\n"],"names":["jsx","cn","jsxs"],"mappings":"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"}
1
+ {"version":3,"file":"MatrixTable.cjs","sources":["../../src/data/MatrixTable.tsx"],"sourcesContent":["import type { ReactNode } from \"react\";\nimport { cn } from \"../lib/utils\";\n\nexport type MatrixTableRow = {\n key: string;\n label: ReactNode;\n cells: ReactNode[];\n};\n\nexport type MatrixTableProps = {\n columns: ReactNode[];\n rows: MatrixTableRow[];\n corner?: ReactNode;\n emptyMessage?: ReactNode;\n angledHeaders?: boolean;\n density?: \"default\" | \"compact\";\n columnWidth?: number;\n headerHeight?: number;\n // maxHeight caps the scroll viewport so the body scrolls under frozen\n // headers (Excel-style freeze panes). Accepts any CSS length; number => px.\n maxHeight?: number | string;\n className?: string;\n columnClassName?: string;\n rowLabelClassName?: string;\n cellClassName?: string;\n // headerClassName is appended to the header row and every header cell (corner\n // + columns). The header has no background by default; use this to add one,\n // e.g. \"bg-muted\", since tailwind-merge lets the later class win.\n headerClassName?: string;\n};\n\nexport function MatrixTable({\n columns,\n rows,\n corner,\n emptyMessage = \"No data\",\n angledHeaders = false,\n density = \"default\",\n columnWidth = 48,\n headerHeight = 120,\n maxHeight,\n className,\n columnClassName,\n rowLabelClassName,\n cellClassName,\n headerClassName,\n}: MatrixTableProps) {\n if (rows.length === 0 || columns.length === 0) {\n return <div className=\"text-sm text-muted-foreground\">{emptyMessage}</div>;\n }\n\n const textWidth = Math.round(headerHeight * 1.41);\n const diagonalOverhang = Math.round(headerHeight * 0.71);\n const compact = density === \"compact\";\n const headerCellPadding = compact ? \"px-density-2 py-density-1\" : \"px-density-3 py-density-2\";\n const rowLabelPadding = compact ? \"px-density-2 py-1\" : \"px-density-3 py-density-2\";\n const bodyCellPadding = compact ? \"px-density-2 py-1\" : \"px-density-3 py-density-2\";\n\n return (\n <div\n className={cn(\"overflow-auto rounded-md border border-border\", className)}\n style={{\n ...(angledHeaders ? { paddingRight: diagonalOverhang } : undefined),\n ...(maxHeight !== undefined ? { maxHeight } : undefined),\n }}\n >\n <table className={cn(\"w-max border-collapse\", compact ? \"text-xs\" : \"text-sm\")}>\n {angledHeaders && (\n <colgroup>\n <col />\n {columns.map((_, index) => (\n <col key={index} style={{ width: columnWidth }} />\n ))}\n </colgroup>\n )}\n <thead>\n <tr className={cn(!angledHeaders && \"border-b border-border\", headerClassName)}>\n <th\n scope=\"col\"\n className={cn(\n \"sticky left-0 top-0 z-30 min-w-44 border-r border-border text-left font-medium\",\n headerCellPadding,\n angledHeaders ? \"align-bottom\" : cn(\"border-b border-border\", columnClassName),\n headerClassName,\n )}\n >\n {corner}\n </th>\n {columns.map((column, index) =>\n angledHeaders ? (\n <th\n key={index}\n scope=\"col\"\n title={columnTitle(column)}\n className={cn(\n \"sticky top-0 z-20 overflow-visible border-b border-border p-0 align-bottom\",\n columnClassName,\n headerClassName,\n )}\n style={{\n width: columnWidth,\n minWidth: columnWidth,\n maxWidth: columnWidth,\n height: headerHeight,\n }}\n >\n <div\n className=\"absolute bottom-0 border-b border-border\"\n style={{\n left: columnWidth,\n width: textWidth,\n transform: \"rotate(-45deg)\",\n transformOrigin: \"0 100%\",\n }}\n />\n {index === 0 && (\n <div\n className=\"absolute bottom-0 border-b border-border\"\n style={{\n left: 0,\n width: textWidth,\n transform: \"rotate(-45deg)\",\n transformOrigin: \"0 100%\",\n }}\n />\n )}\n <div\n className=\"absolute bottom-2 overflow-hidden text-ellipsis whitespace-nowrap pl-1 text-left text-xs font-medium leading-none text-muted-foreground\"\n style={{\n left: columnWidth / 2,\n width: textWidth,\n transform: \"rotate(-45deg)\",\n transformOrigin: \"0 100%\",\n }}\n >\n {column}\n </div>\n </th>\n ) : (\n <th\n key={index}\n scope=\"col\"\n className={cn(\n \"sticky top-0 z-20 min-w-24 whitespace-nowrap border-b border-border text-center text-xs font-medium text-muted-foreground\",\n headerCellPadding,\n columnClassName,\n headerClassName,\n )}\n >\n {column}\n </th>\n ),\n )}\n </tr>\n </thead>\n <tbody>\n {rows.map((row) => (\n <tr key={row.key} className=\"border-b border-border last:border-b-0\">\n <th\n scope=\"row\"\n className={cn(\n \"sticky left-0 z-10 border-r border-border bg-background text-left font-medium\",\n rowLabelPadding,\n rowLabelClassName,\n )}\n >\n {row.label}\n </th>\n {columns.map((_, index) => (\n <td\n key={index}\n className={cn(\n angledHeaders\n ? \"p-0 text-center align-middle\"\n : cn(bodyCellPadding, \"text-center align-middle\"),\n cellClassName,\n )}\n style={\n angledHeaders\n ? {\n width: columnWidth,\n minWidth: columnWidth,\n maxWidth: columnWidth,\n }\n : undefined\n }\n >\n {row.cells[index] ?? null}\n </td>\n ))}\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n );\n}\n\nfunction columnTitle(column: ReactNode) {\n if (typeof column === \"string\" || typeof column === \"number\") {\n return String(column);\n }\n return undefined;\n}\n"],"names":["jsx","cn","jsxs"],"mappings":"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"}
@@ -38,13 +38,13 @@ function MatrixTable({
38
38
  /* @__PURE__ */ jsx("col", {}),
39
39
  columns.map((_, index) => /* @__PURE__ */ jsx("col", { style: { width: columnWidth } }, index))
40
40
  ] }),
41
- /* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsxs("tr", { className: cn("bg-muted/40", !angledHeaders && "border-b border-border", headerClassName), children: [
41
+ /* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsxs("tr", { className: cn(!angledHeaders && "border-b border-border", headerClassName), children: [
42
42
  /* @__PURE__ */ jsx(
43
43
  "th",
44
44
  {
45
45
  scope: "col",
46
46
  className: cn(
47
- "sticky left-0 top-0 z-30 min-w-44 border-r border-border bg-muted text-left font-medium",
47
+ "sticky left-0 top-0 z-30 min-w-44 border-r border-border text-left font-medium",
48
48
  headerCellPadding,
49
49
  angledHeaders ? "align-bottom" : cn("border-b border-border", columnClassName),
50
50
  headerClassName
@@ -59,7 +59,7 @@ function MatrixTable({
59
59
  scope: "col",
60
60
  title: columnTitle(column),
61
61
  className: cn(
62
- "sticky top-0 z-20 overflow-visible border-b border-border bg-muted p-0 align-bottom",
62
+ "sticky top-0 z-20 overflow-visible border-b border-border p-0 align-bottom",
63
63
  columnClassName,
64
64
  headerClassName
65
65
  ),
@@ -115,7 +115,7 @@ function MatrixTable({
115
115
  {
116
116
  scope: "col",
117
117
  className: cn(
118
- "sticky top-0 z-20 min-w-24 whitespace-nowrap border-b border-border bg-muted text-center text-xs font-medium text-muted-foreground",
118
+ "sticky top-0 z-20 min-w-24 whitespace-nowrap border-b border-border text-center text-xs font-medium text-muted-foreground",
119
119
  headerCellPadding,
120
120
  columnClassName,
121
121
  headerClassName
@@ -1 +1 @@
1
- {"version":3,"file":"MatrixTable.js","sources":["../../src/data/MatrixTable.tsx"],"sourcesContent":["import type { ReactNode } from \"react\";\nimport { cn } from \"../lib/utils\";\n\nexport type MatrixTableRow = {\n key: string;\n label: ReactNode;\n cells: ReactNode[];\n};\n\nexport type MatrixTableProps = {\n columns: ReactNode[];\n rows: MatrixTableRow[];\n corner?: ReactNode;\n emptyMessage?: ReactNode;\n angledHeaders?: boolean;\n density?: \"default\" | \"compact\";\n columnWidth?: number;\n headerHeight?: number;\n // maxHeight caps the scroll viewport so the body scrolls under frozen\n // headers (Excel-style freeze panes). Accepts any CSS length; number => px.\n maxHeight?: number | string;\n className?: string;\n columnClassName?: string;\n rowLabelClassName?: string;\n cellClassName?: string;\n // headerClassName is appended to the header row and every header cell (corner\n // + columns). Use it to override the default gray header background, e.g.\n // \"bg-transparent\", since tailwind-merge lets the later class win.\n headerClassName?: string;\n};\n\nexport function MatrixTable({\n columns,\n rows,\n corner,\n emptyMessage = \"No data\",\n angledHeaders = false,\n density = \"default\",\n columnWidth = 48,\n headerHeight = 120,\n maxHeight,\n className,\n columnClassName,\n rowLabelClassName,\n cellClassName,\n headerClassName,\n}: MatrixTableProps) {\n if (rows.length === 0 || columns.length === 0) {\n return <div className=\"text-sm text-muted-foreground\">{emptyMessage}</div>;\n }\n\n const textWidth = Math.round(headerHeight * 1.41);\n const diagonalOverhang = Math.round(headerHeight * 0.71);\n const compact = density === \"compact\";\n const headerCellPadding = compact ? \"px-density-2 py-density-1\" : \"px-density-3 py-density-2\";\n const rowLabelPadding = compact ? \"px-density-2 py-1\" : \"px-density-3 py-density-2\";\n const bodyCellPadding = compact ? \"px-density-2 py-1\" : \"px-density-3 py-density-2\";\n\n return (\n <div\n className={cn(\"overflow-auto rounded-md border border-border\", className)}\n style={{\n ...(angledHeaders ? { paddingRight: diagonalOverhang } : undefined),\n ...(maxHeight !== undefined ? { maxHeight } : undefined),\n }}\n >\n <table className={cn(\"w-max border-collapse\", compact ? \"text-xs\" : \"text-sm\")}>\n {angledHeaders && (\n <colgroup>\n <col />\n {columns.map((_, index) => (\n <col key={index} style={{ width: columnWidth }} />\n ))}\n </colgroup>\n )}\n <thead>\n <tr className={cn(\"bg-muted/40\", !angledHeaders && \"border-b border-border\", headerClassName)}>\n <th\n scope=\"col\"\n className={cn(\n \"sticky left-0 top-0 z-30 min-w-44 border-r border-border bg-muted text-left font-medium\",\n headerCellPadding,\n angledHeaders ? \"align-bottom\" : cn(\"border-b border-border\", columnClassName),\n headerClassName,\n )}\n >\n {corner}\n </th>\n {columns.map((column, index) =>\n angledHeaders ? (\n <th\n key={index}\n scope=\"col\"\n title={columnTitle(column)}\n className={cn(\n \"sticky top-0 z-20 overflow-visible border-b border-border bg-muted p-0 align-bottom\",\n columnClassName,\n headerClassName,\n )}\n style={{\n width: columnWidth,\n minWidth: columnWidth,\n maxWidth: columnWidth,\n height: headerHeight,\n }}\n >\n <div\n className=\"absolute bottom-0 border-b border-border\"\n style={{\n left: columnWidth,\n width: textWidth,\n transform: \"rotate(-45deg)\",\n transformOrigin: \"0 100%\",\n }}\n />\n {index === 0 && (\n <div\n className=\"absolute bottom-0 border-b border-border\"\n style={{\n left: 0,\n width: textWidth,\n transform: \"rotate(-45deg)\",\n transformOrigin: \"0 100%\",\n }}\n />\n )}\n <div\n className=\"absolute bottom-2 overflow-hidden text-ellipsis whitespace-nowrap pl-1 text-left text-xs font-medium leading-none text-muted-foreground\"\n style={{\n left: columnWidth / 2,\n width: textWidth,\n transform: \"rotate(-45deg)\",\n transformOrigin: \"0 100%\",\n }}\n >\n {column}\n </div>\n </th>\n ) : (\n <th\n key={index}\n scope=\"col\"\n className={cn(\n \"sticky top-0 z-20 min-w-24 whitespace-nowrap border-b border-border bg-muted text-center text-xs font-medium text-muted-foreground\",\n headerCellPadding,\n columnClassName,\n headerClassName,\n )}\n >\n {column}\n </th>\n ),\n )}\n </tr>\n </thead>\n <tbody>\n {rows.map((row) => (\n <tr key={row.key} className=\"border-b border-border last:border-b-0\">\n <th\n scope=\"row\"\n className={cn(\n \"sticky left-0 z-10 border-r border-border bg-background text-left font-medium\",\n rowLabelPadding,\n rowLabelClassName,\n )}\n >\n {row.label}\n </th>\n {columns.map((_, index) => (\n <td\n key={index}\n className={cn(\n angledHeaders\n ? \"p-0 text-center align-middle\"\n : cn(bodyCellPadding, \"text-center align-middle\"),\n cellClassName,\n )}\n style={\n angledHeaders\n ? {\n width: columnWidth,\n minWidth: columnWidth,\n maxWidth: columnWidth,\n }\n : undefined\n }\n >\n {row.cells[index] ?? null}\n </td>\n ))}\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n );\n}\n\nfunction columnTitle(column: ReactNode) {\n if (typeof column === \"string\" || typeof column === \"number\") {\n return String(column);\n }\n return undefined;\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"MatrixTable.js","sources":["../../src/data/MatrixTable.tsx"],"sourcesContent":["import type { ReactNode } from \"react\";\nimport { cn } from \"../lib/utils\";\n\nexport type MatrixTableRow = {\n key: string;\n label: ReactNode;\n cells: ReactNode[];\n};\n\nexport type MatrixTableProps = {\n columns: ReactNode[];\n rows: MatrixTableRow[];\n corner?: ReactNode;\n emptyMessage?: ReactNode;\n angledHeaders?: boolean;\n density?: \"default\" | \"compact\";\n columnWidth?: number;\n headerHeight?: number;\n // maxHeight caps the scroll viewport so the body scrolls under frozen\n // headers (Excel-style freeze panes). Accepts any CSS length; number => px.\n maxHeight?: number | string;\n className?: string;\n columnClassName?: string;\n rowLabelClassName?: string;\n cellClassName?: string;\n // headerClassName is appended to the header row and every header cell (corner\n // + columns). The header has no background by default; use this to add one,\n // e.g. \"bg-muted\", since tailwind-merge lets the later class win.\n headerClassName?: string;\n};\n\nexport function MatrixTable({\n columns,\n rows,\n corner,\n emptyMessage = \"No data\",\n angledHeaders = false,\n density = \"default\",\n columnWidth = 48,\n headerHeight = 120,\n maxHeight,\n className,\n columnClassName,\n rowLabelClassName,\n cellClassName,\n headerClassName,\n}: MatrixTableProps) {\n if (rows.length === 0 || columns.length === 0) {\n return <div className=\"text-sm text-muted-foreground\">{emptyMessage}</div>;\n }\n\n const textWidth = Math.round(headerHeight * 1.41);\n const diagonalOverhang = Math.round(headerHeight * 0.71);\n const compact = density === \"compact\";\n const headerCellPadding = compact ? \"px-density-2 py-density-1\" : \"px-density-3 py-density-2\";\n const rowLabelPadding = compact ? \"px-density-2 py-1\" : \"px-density-3 py-density-2\";\n const bodyCellPadding = compact ? \"px-density-2 py-1\" : \"px-density-3 py-density-2\";\n\n return (\n <div\n className={cn(\"overflow-auto rounded-md border border-border\", className)}\n style={{\n ...(angledHeaders ? { paddingRight: diagonalOverhang } : undefined),\n ...(maxHeight !== undefined ? { maxHeight } : undefined),\n }}\n >\n <table className={cn(\"w-max border-collapse\", compact ? \"text-xs\" : \"text-sm\")}>\n {angledHeaders && (\n <colgroup>\n <col />\n {columns.map((_, index) => (\n <col key={index} style={{ width: columnWidth }} />\n ))}\n </colgroup>\n )}\n <thead>\n <tr className={cn(!angledHeaders && \"border-b border-border\", headerClassName)}>\n <th\n scope=\"col\"\n className={cn(\n \"sticky left-0 top-0 z-30 min-w-44 border-r border-border text-left font-medium\",\n headerCellPadding,\n angledHeaders ? \"align-bottom\" : cn(\"border-b border-border\", columnClassName),\n headerClassName,\n )}\n >\n {corner}\n </th>\n {columns.map((column, index) =>\n angledHeaders ? (\n <th\n key={index}\n scope=\"col\"\n title={columnTitle(column)}\n className={cn(\n \"sticky top-0 z-20 overflow-visible border-b border-border p-0 align-bottom\",\n columnClassName,\n headerClassName,\n )}\n style={{\n width: columnWidth,\n minWidth: columnWidth,\n maxWidth: columnWidth,\n height: headerHeight,\n }}\n >\n <div\n className=\"absolute bottom-0 border-b border-border\"\n style={{\n left: columnWidth,\n width: textWidth,\n transform: \"rotate(-45deg)\",\n transformOrigin: \"0 100%\",\n }}\n />\n {index === 0 && (\n <div\n className=\"absolute bottom-0 border-b border-border\"\n style={{\n left: 0,\n width: textWidth,\n transform: \"rotate(-45deg)\",\n transformOrigin: \"0 100%\",\n }}\n />\n )}\n <div\n className=\"absolute bottom-2 overflow-hidden text-ellipsis whitespace-nowrap pl-1 text-left text-xs font-medium leading-none text-muted-foreground\"\n style={{\n left: columnWidth / 2,\n width: textWidth,\n transform: \"rotate(-45deg)\",\n transformOrigin: \"0 100%\",\n }}\n >\n {column}\n </div>\n </th>\n ) : (\n <th\n key={index}\n scope=\"col\"\n className={cn(\n \"sticky top-0 z-20 min-w-24 whitespace-nowrap border-b border-border text-center text-xs font-medium text-muted-foreground\",\n headerCellPadding,\n columnClassName,\n headerClassName,\n )}\n >\n {column}\n </th>\n ),\n )}\n </tr>\n </thead>\n <tbody>\n {rows.map((row) => (\n <tr key={row.key} className=\"border-b border-border last:border-b-0\">\n <th\n scope=\"row\"\n className={cn(\n \"sticky left-0 z-10 border-r border-border bg-background text-left font-medium\",\n rowLabelPadding,\n rowLabelClassName,\n )}\n >\n {row.label}\n </th>\n {columns.map((_, index) => (\n <td\n key={index}\n className={cn(\n angledHeaders\n ? \"p-0 text-center align-middle\"\n : cn(bodyCellPadding, \"text-center align-middle\"),\n cellClassName,\n )}\n style={\n angledHeaders\n ? {\n width: columnWidth,\n minWidth: columnWidth,\n maxWidth: columnWidth,\n }\n : undefined\n }\n >\n {row.cells[index] ?? null}\n </td>\n ))}\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n );\n}\n\nfunction columnTitle(column: ReactNode) {\n if (typeof column === \"string\" || typeof column === \"number\") {\n return String(column);\n }\n return undefined;\n}\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,76 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const jsxRuntime = require("react/jsx-runtime");
4
+ const utils = require("../lib/utils.cjs");
5
+ const arcToneClass = {
6
+ neutral: "text-foreground",
7
+ success: "text-green-500",
8
+ warning: "text-yellow-500",
9
+ danger: "text-red-500",
10
+ info: "text-blue-500"
11
+ };
12
+ function RadialGauge({
13
+ value,
14
+ max = 100,
15
+ size = 28,
16
+ thickness = 3,
17
+ tone = "neutral",
18
+ center,
19
+ label,
20
+ title,
21
+ className
22
+ }) {
23
+ const clamped = Math.max(0, Math.min(max, value));
24
+ const pct = max > 0 ? clamped / max : 0;
25
+ const radius = (size - thickness) / 2;
26
+ const circumference = 2 * Math.PI * radius;
27
+ const offset = circumference * (1 - pct);
28
+ return /* @__PURE__ */ jsxRuntime.jsxs(
29
+ "span",
30
+ {
31
+ className: utils.cn("inline-flex items-center gap-1.5", className),
32
+ title,
33
+ role: "meter",
34
+ "aria-valuenow": clamped,
35
+ "aria-valuemin": 0,
36
+ "aria-valuemax": max,
37
+ children: [
38
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "relative inline-flex shrink-0", style: { width: size, height: size }, children: [
39
+ /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: size, height: size, className: "-rotate-90", children: [
40
+ /* @__PURE__ */ jsxRuntime.jsx(
41
+ "circle",
42
+ {
43
+ className: "text-muted-foreground/20",
44
+ stroke: "currentColor",
45
+ fill: "none",
46
+ strokeWidth: thickness,
47
+ r: radius,
48
+ cx: size / 2,
49
+ cy: size / 2
50
+ }
51
+ ),
52
+ /* @__PURE__ */ jsxRuntime.jsx(
53
+ "circle",
54
+ {
55
+ className: utils.cn("transition-[stroke-dashoffset] duration-500", arcToneClass[tone]),
56
+ stroke: "currentColor",
57
+ fill: "none",
58
+ strokeWidth: thickness,
59
+ strokeLinecap: "round",
60
+ strokeDasharray: circumference,
61
+ strokeDashoffset: offset,
62
+ r: radius,
63
+ cx: size / 2,
64
+ cy: size / 2
65
+ }
66
+ )
67
+ ] }),
68
+ center != null && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "absolute inset-0 flex items-center justify-center", children: center })
69
+ ] }),
70
+ label != null && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-muted-foreground", children: label })
71
+ ]
72
+ }
73
+ );
74
+ }
75
+ exports.RadialGauge = RadialGauge;
76
+ //# sourceMappingURL=RadialGauge.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RadialGauge.cjs","sources":["../../src/data/RadialGauge.tsx"],"sourcesContent":["import type { ReactNode } from \"react\";\nimport { cn } from \"../lib/utils\";\nimport type { GaugeTone } from \"./Gauge\";\n\nexport type RadialGaugeProps = {\n /** Current value. Clamped to [0, max]. */\n value: number;\n /** Value that fills the ring completely. */\n max?: number;\n /** Outer diameter in pixels. */\n size?: number;\n /** Ring thickness in pixels. */\n thickness?: number;\n /** Arc color. Defaults to neutral. */\n tone?: GaugeTone;\n /** Content rendered centered inside the ring (icon, number, …). */\n center?: ReactNode;\n /** Text rendered to the right of the ring. */\n label?: ReactNode;\n /** Native tooltip / accessible title. */\n title?: string;\n /** Classes applied to the root flex row. */\n className?: string;\n};\n\nconst arcToneClass: Record<GaugeTone, string> = {\n neutral: \"text-foreground\",\n success: \"text-green-500\",\n warning: \"text-yellow-500\",\n danger: \"text-red-500\",\n info: \"text-blue-500\",\n};\n\nexport function RadialGauge({\n value,\n max = 100,\n size = 28,\n thickness = 3,\n tone = \"neutral\",\n center,\n label,\n title,\n className,\n}: RadialGaugeProps) {\n const clamped = Math.max(0, Math.min(max, value));\n const pct = max > 0 ? clamped / max : 0;\n const radius = (size - thickness) / 2;\n const circumference = 2 * Math.PI * radius;\n const offset = circumference * (1 - pct);\n\n return (\n <span\n className={cn(\"inline-flex items-center gap-1.5\", className)}\n title={title}\n role=\"meter\"\n aria-valuenow={clamped}\n aria-valuemin={0}\n aria-valuemax={max}\n >\n <span className=\"relative inline-flex shrink-0\" style={{ width: size, height: size }}>\n <svg width={size} height={size} className=\"-rotate-90\">\n <circle\n className=\"text-muted-foreground/20\"\n stroke=\"currentColor\"\n fill=\"none\"\n strokeWidth={thickness}\n r={radius}\n cx={size / 2}\n cy={size / 2}\n />\n <circle\n className={cn(\"transition-[stroke-dashoffset] duration-500\", arcToneClass[tone])}\n stroke=\"currentColor\"\n fill=\"none\"\n strokeWidth={thickness}\n strokeLinecap=\"round\"\n strokeDasharray={circumference}\n strokeDashoffset={offset}\n r={radius}\n cx={size / 2}\n cy={size / 2}\n />\n </svg>\n {center != null && (\n <span className=\"absolute inset-0 flex items-center justify-center\">{center}</span>\n )}\n </span>\n {label != null && <span className=\"text-xs text-muted-foreground\">{label}</span>}\n </span>\n );\n}\n"],"names":["jsxs","cn","jsx"],"mappings":";;;;AAyBA,MAAM,eAA0C;AAAA,EAC9C,SAAS;AAAA,EACT,SAAS;AAAA,EACT,SAAS;AAAA,EACT,QAAQ;AAAA,EACR,MAAM;AACR;AAEO,SAAS,YAAY;AAAA,EAC1B;AAAA,EACA,MAAM;AAAA,EACN,OAAO;AAAA,EACP,YAAY;AAAA,EACZ,OAAO;AAAA,EACP;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAqB;AACnB,QAAM,UAAU,KAAK,IAAI,GAAG,KAAK,IAAI,KAAK,KAAK,CAAC;AAChD,QAAM,MAAM,MAAM,IAAI,UAAU,MAAM;AACtC,QAAM,UAAU,OAAO,aAAa;AACpC,QAAM,gBAAgB,IAAI,KAAK,KAAK;AACpC,QAAM,SAAS,iBAAiB,IAAI;AAEpC,SACEA,2BAAAA;AAAAA,IAAC;AAAA,IAAA;AAAA,MACC,WAAWC,MAAAA,GAAG,oCAAoC,SAAS;AAAA,MAC3D;AAAA,MACA,MAAK;AAAA,MACL,iBAAe;AAAA,MACf,iBAAe;AAAA,MACf,iBAAe;AAAA,MAEf,UAAA;AAAA,QAAAD,2BAAAA,KAAC,QAAA,EAAK,WAAU,iCAAgC,OAAO,EAAE,OAAO,MAAM,QAAQ,KAAA,GAC5E,UAAA;AAAA,UAAAA,gCAAC,SAAI,OAAO,MAAM,QAAQ,MAAM,WAAU,cACxC,UAAA;AAAA,YAAAE,2BAAAA;AAAAA,cAAC;AAAA,cAAA;AAAA,gBACC,WAAU;AAAA,gBACV,QAAO;AAAA,gBACP,MAAK;AAAA,gBACL,aAAa;AAAA,gBACb,GAAG;AAAA,gBACH,IAAI,OAAO;AAAA,gBACX,IAAI,OAAO;AAAA,cAAA;AAAA,YAAA;AAAA,YAEbA,2BAAAA;AAAAA,cAAC;AAAA,cAAA;AAAA,gBACC,WAAWD,MAAAA,GAAG,+CAA+C,aAAa,IAAI,CAAC;AAAA,gBAC/E,QAAO;AAAA,gBACP,MAAK;AAAA,gBACL,aAAa;AAAA,gBACb,eAAc;AAAA,gBACd,iBAAiB;AAAA,gBACjB,kBAAkB;AAAA,gBAClB,GAAG;AAAA,gBACH,IAAI,OAAO;AAAA,gBACX,IAAI,OAAO;AAAA,cAAA;AAAA,YAAA;AAAA,UACb,GACF;AAAA,UACC,UAAU,QACTC,2BAAAA,IAAC,QAAA,EAAK,WAAU,qDAAqD,UAAA,OAAA,CAAO;AAAA,QAAA,GAEhF;AAAA,QACC,SAAS,QAAQA,2BAAAA,IAAC,QAAA,EAAK,WAAU,iCAAiC,UAAA,MAAA,CAAM;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA;AAG/E;;"}
@@ -0,0 +1,24 @@
1
+ import { ReactNode } from 'react';
2
+ import { GaugeTone } from './Gauge';
3
+ export type RadialGaugeProps = {
4
+ /** Current value. Clamped to [0, max]. */
5
+ value: number;
6
+ /** Value that fills the ring completely. */
7
+ max?: number;
8
+ /** Outer diameter in pixels. */
9
+ size?: number;
10
+ /** Ring thickness in pixels. */
11
+ thickness?: number;
12
+ /** Arc color. Defaults to neutral. */
13
+ tone?: GaugeTone;
14
+ /** Content rendered centered inside the ring (icon, number, …). */
15
+ center?: ReactNode;
16
+ /** Text rendered to the right of the ring. */
17
+ label?: ReactNode;
18
+ /** Native tooltip / accessible title. */
19
+ title?: string;
20
+ /** Classes applied to the root flex row. */
21
+ className?: string;
22
+ };
23
+ export declare function RadialGauge({ value, max, size, thickness, tone, center, label, title, className, }: RadialGaugeProps): import("react/jsx-runtime").JSX.Element;
24
+ //# sourceMappingURL=RadialGauge.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RadialGauge.d.ts","sourceRoot":"","sources":["../../src/data/RadialGauge.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAEzC,MAAM,MAAM,gBAAgB,GAAG;IAC7B,0CAA0C;IAC1C,KAAK,EAAE,MAAM,CAAC;IACd,4CAA4C;IAC5C,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,gCAAgC;IAChC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,gCAAgC;IAChC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,sCAAsC;IACtC,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,mEAAmE;IACnE,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,8CAA8C;IAC9C,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,yCAAyC;IACzC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,4CAA4C;IAC5C,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAUF,wBAAgB,WAAW,CAAC,EAC1B,KAAK,EACL,GAAS,EACT,IAAS,EACT,SAAa,EACb,IAAgB,EAChB,MAAM,EACN,KAAK,EACL,KAAK,EACL,SAAS,GACV,EAAE,gBAAgB,2CA+ClB"}
@@ -0,0 +1,76 @@
1
+ import { jsxs, jsx } from "react/jsx-runtime";
2
+ import { cn } from "../lib/utils.js";
3
+ const arcToneClass = {
4
+ neutral: "text-foreground",
5
+ success: "text-green-500",
6
+ warning: "text-yellow-500",
7
+ danger: "text-red-500",
8
+ info: "text-blue-500"
9
+ };
10
+ function RadialGauge({
11
+ value,
12
+ max = 100,
13
+ size = 28,
14
+ thickness = 3,
15
+ tone = "neutral",
16
+ center,
17
+ label,
18
+ title,
19
+ className
20
+ }) {
21
+ const clamped = Math.max(0, Math.min(max, value));
22
+ const pct = max > 0 ? clamped / max : 0;
23
+ const radius = (size - thickness) / 2;
24
+ const circumference = 2 * Math.PI * radius;
25
+ const offset = circumference * (1 - pct);
26
+ return /* @__PURE__ */ jsxs(
27
+ "span",
28
+ {
29
+ className: cn("inline-flex items-center gap-1.5", className),
30
+ title,
31
+ role: "meter",
32
+ "aria-valuenow": clamped,
33
+ "aria-valuemin": 0,
34
+ "aria-valuemax": max,
35
+ children: [
36
+ /* @__PURE__ */ jsxs("span", { className: "relative inline-flex shrink-0", style: { width: size, height: size }, children: [
37
+ /* @__PURE__ */ jsxs("svg", { width: size, height: size, className: "-rotate-90", children: [
38
+ /* @__PURE__ */ jsx(
39
+ "circle",
40
+ {
41
+ className: "text-muted-foreground/20",
42
+ stroke: "currentColor",
43
+ fill: "none",
44
+ strokeWidth: thickness,
45
+ r: radius,
46
+ cx: size / 2,
47
+ cy: size / 2
48
+ }
49
+ ),
50
+ /* @__PURE__ */ jsx(
51
+ "circle",
52
+ {
53
+ className: cn("transition-[stroke-dashoffset] duration-500", arcToneClass[tone]),
54
+ stroke: "currentColor",
55
+ fill: "none",
56
+ strokeWidth: thickness,
57
+ strokeLinecap: "round",
58
+ strokeDasharray: circumference,
59
+ strokeDashoffset: offset,
60
+ r: radius,
61
+ cx: size / 2,
62
+ cy: size / 2
63
+ }
64
+ )
65
+ ] }),
66
+ center != null && /* @__PURE__ */ jsx("span", { className: "absolute inset-0 flex items-center justify-center", children: center })
67
+ ] }),
68
+ label != null && /* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground", children: label })
69
+ ]
70
+ }
71
+ );
72
+ }
73
+ export {
74
+ RadialGauge
75
+ };
76
+ //# sourceMappingURL=RadialGauge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RadialGauge.js","sources":["../../src/data/RadialGauge.tsx"],"sourcesContent":["import type { ReactNode } from \"react\";\nimport { cn } from \"../lib/utils\";\nimport type { GaugeTone } from \"./Gauge\";\n\nexport type RadialGaugeProps = {\n /** Current value. Clamped to [0, max]. */\n value: number;\n /** Value that fills the ring completely. */\n max?: number;\n /** Outer diameter in pixels. */\n size?: number;\n /** Ring thickness in pixels. */\n thickness?: number;\n /** Arc color. Defaults to neutral. */\n tone?: GaugeTone;\n /** Content rendered centered inside the ring (icon, number, …). */\n center?: ReactNode;\n /** Text rendered to the right of the ring. */\n label?: ReactNode;\n /** Native tooltip / accessible title. */\n title?: string;\n /** Classes applied to the root flex row. */\n className?: string;\n};\n\nconst arcToneClass: Record<GaugeTone, string> = {\n neutral: \"text-foreground\",\n success: \"text-green-500\",\n warning: \"text-yellow-500\",\n danger: \"text-red-500\",\n info: \"text-blue-500\",\n};\n\nexport function RadialGauge({\n value,\n max = 100,\n size = 28,\n thickness = 3,\n tone = \"neutral\",\n center,\n label,\n title,\n className,\n}: RadialGaugeProps) {\n const clamped = Math.max(0, Math.min(max, value));\n const pct = max > 0 ? clamped / max : 0;\n const radius = (size - thickness) / 2;\n const circumference = 2 * Math.PI * radius;\n const offset = circumference * (1 - pct);\n\n return (\n <span\n className={cn(\"inline-flex items-center gap-1.5\", className)}\n title={title}\n role=\"meter\"\n aria-valuenow={clamped}\n aria-valuemin={0}\n aria-valuemax={max}\n >\n <span className=\"relative inline-flex shrink-0\" style={{ width: size, height: size }}>\n <svg width={size} height={size} className=\"-rotate-90\">\n <circle\n className=\"text-muted-foreground/20\"\n stroke=\"currentColor\"\n fill=\"none\"\n strokeWidth={thickness}\n r={radius}\n cx={size / 2}\n cy={size / 2}\n />\n <circle\n className={cn(\"transition-[stroke-dashoffset] duration-500\", arcToneClass[tone])}\n stroke=\"currentColor\"\n fill=\"none\"\n strokeWidth={thickness}\n strokeLinecap=\"round\"\n strokeDasharray={circumference}\n strokeDashoffset={offset}\n r={radius}\n cx={size / 2}\n cy={size / 2}\n />\n </svg>\n {center != null && (\n <span className=\"absolute inset-0 flex items-center justify-center\">{center}</span>\n )}\n </span>\n {label != null && <span className=\"text-xs text-muted-foreground\">{label}</span>}\n </span>\n );\n}\n"],"names":[],"mappings":";;AAyBA,MAAM,eAA0C;AAAA,EAC9C,SAAS;AAAA,EACT,SAAS;AAAA,EACT,SAAS;AAAA,EACT,QAAQ;AAAA,EACR,MAAM;AACR;AAEO,SAAS,YAAY;AAAA,EAC1B;AAAA,EACA,MAAM;AAAA,EACN,OAAO;AAAA,EACP,YAAY;AAAA,EACZ,OAAO;AAAA,EACP;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAqB;AACnB,QAAM,UAAU,KAAK,IAAI,GAAG,KAAK,IAAI,KAAK,KAAK,CAAC;AAChD,QAAM,MAAM,MAAM,IAAI,UAAU,MAAM;AACtC,QAAM,UAAU,OAAO,aAAa;AACpC,QAAM,gBAAgB,IAAI,KAAK,KAAK;AACpC,QAAM,SAAS,iBAAiB,IAAI;AAEpC,SACE;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,WAAW,GAAG,oCAAoC,SAAS;AAAA,MAC3D;AAAA,MACA,MAAK;AAAA,MACL,iBAAe;AAAA,MACf,iBAAe;AAAA,MACf,iBAAe;AAAA,MAEf,UAAA;AAAA,QAAA,qBAAC,QAAA,EAAK,WAAU,iCAAgC,OAAO,EAAE,OAAO,MAAM,QAAQ,KAAA,GAC5E,UAAA;AAAA,UAAA,qBAAC,SAAI,OAAO,MAAM,QAAQ,MAAM,WAAU,cACxC,UAAA;AAAA,YAAA;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC,WAAU;AAAA,gBACV,QAAO;AAAA,gBACP,MAAK;AAAA,gBACL,aAAa;AAAA,gBACb,GAAG;AAAA,gBACH,IAAI,OAAO;AAAA,gBACX,IAAI,OAAO;AAAA,cAAA;AAAA,YAAA;AAAA,YAEb;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC,WAAW,GAAG,+CAA+C,aAAa,IAAI,CAAC;AAAA,gBAC/E,QAAO;AAAA,gBACP,MAAK;AAAA,gBACL,aAAa;AAAA,gBACb,eAAc;AAAA,gBACd,iBAAiB;AAAA,gBACjB,kBAAkB;AAAA,gBAClB,GAAG;AAAA,gBACH,IAAI,OAAO;AAAA,gBACX,IAAI,OAAO;AAAA,cAAA;AAAA,YAAA;AAAA,UACb,GACF;AAAA,UACC,UAAU,QACT,oBAAC,QAAA,EAAK,WAAU,qDAAqD,UAAA,OAAA,CAAO;AAAA,QAAA,GAEhF;AAAA,QACC,SAAS,QAAQ,oBAAC,QAAA,EAAK,WAAU,iCAAiC,UAAA,MAAA,CAAM;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA;AAG/E;"}