@mastra/playground-ui 68.0.0-alpha.1 → 68.0.0-alpha.3

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 (536) hide show
  1. package/dist/{DataCodeSection-CcPmJPTp.cjs → DataCodeSection-CFxXsQWH.cjs} +3 -3
  2. package/dist/DataCodeSection-CFxXsQWH.cjs.map +1 -0
  3. package/dist/{DataCodeSection-KJRyRD1Q.js → DataCodeSection-PY9XEg2C.js} +3 -3
  4. package/dist/DataCodeSection-PY9XEg2C.js.map +1 -0
  5. package/dist/{DataPanel-BwB1Oifd.cjs → DataPanel-Coc9h35I.cjs} +2 -2
  6. package/dist/{DataPanel-BwB1Oifd.cjs.map → DataPanel-Coc9h35I.cjs.map} +1 -1
  7. package/dist/{DataPanel-Bv4M17xO.js → DataPanel-IgB9D5PO.js} +2 -2
  8. package/dist/{DataPanel-Bv4M17xO.js.map → DataPanel-IgB9D5PO.js.map} +1 -1
  9. package/dist/{FilterBar-BO-vvvyq.js → FilterBar-BgW2dqRQ.js} +7 -7
  10. package/dist/FilterBar-BgW2dqRQ.js.map +1 -0
  11. package/dist/{FilterBar-Buw0tv51.cjs → FilterBar-CQl04O6t.cjs} +7 -7
  12. package/dist/FilterBar-CQl04O6t.cjs.map +1 -0
  13. package/dist/KnowledgePageGraph.css +55 -0
  14. package/dist/{MarkdownRenderer-2GOXQJEv.js → MarkdownRenderer-CI30RqdB.js} +19 -6
  15. package/dist/MarkdownRenderer-CI30RqdB.js.map +1 -0
  16. package/dist/{MarkdownRenderer-CB8Z_CHc.cjs → MarkdownRenderer-y65WGBhC.cjs} +19 -6
  17. package/dist/MarkdownRenderer-y65WGBhC.cjs.map +1 -0
  18. package/dist/{MetricsTable-D-aZf3dk.cjs → MetricsTable-BSl81oNe.cjs} +44 -9
  19. package/dist/MetricsTable-BSl81oNe.cjs.map +1 -0
  20. package/dist/{MetricsTable-CRPeLHe1.js → MetricsTable-DID6LRoP.js} +44 -9
  21. package/dist/MetricsTable-DID6LRoP.js.map +1 -0
  22. package/dist/{activity-rJ1NQl_2.js → activity-C8Ql81WM.js} +2 -2
  23. package/dist/{activity-rJ1NQl_2.js.map → activity-C8Ql81WM.js.map} +1 -1
  24. package/dist/{activity-DyB5H3gF.cjs → activity-CcQZeDYi.cjs} +2 -2
  25. package/dist/{activity-DyB5H3gF.cjs.map → activity-CcQZeDYi.cjs.map} +1 -1
  26. package/dist/{ask-user-DdYz56qH.cjs → ask-user-C1p2PEYe.cjs} +2 -2
  27. package/dist/ask-user-C1p2PEYe.cjs.map +1 -0
  28. package/dist/{ask-user-B225wzWc.js → ask-user-DPznrqGO.js} +2 -2
  29. package/dist/ask-user-DPznrqGO.js.map +1 -0
  30. package/dist/chart-plot.css +5 -4
  31. package/dist/{combobox-CtCK0mNx.js → combobox-D21no8t5.js} +4 -4
  32. package/dist/{combobox-CtCK0mNx.js.map → combobox-D21no8t5.js.map} +1 -1
  33. package/dist/{combobox-CMx2ayFN.cjs → combobox-DIT_6xiG.cjs} +4 -4
  34. package/dist/combobox-DIT_6xiG.cjs.map +1 -0
  35. package/dist/{combobox-parts-ScKcYjMR.cjs → combobox-parts-C4phOq4t.cjs} +2 -2
  36. package/dist/combobox-parts-C4phOq4t.cjs.map +1 -0
  37. package/dist/{combobox-parts-C1CugUAU.js → combobox-parts-D90ir0Py.js} +3 -3
  38. package/dist/combobox-parts-D90ir0Py.js.map +1 -0
  39. package/dist/components/Combobox.cjs.js +2 -2
  40. package/dist/components/Combobox.es.js +2 -2
  41. package/dist/components/Command.cjs.js +1 -1
  42. package/dist/components/Command.cjs.js.map +1 -1
  43. package/dist/components/Command.es.js +1 -1
  44. package/dist/components/Command.es.js.map +1 -1
  45. package/dist/components/DataCodeSection.cjs.js +1 -1
  46. package/dist/components/DataCodeSection.es.js +1 -1
  47. package/dist/components/DataList.cjs.js +1 -1
  48. package/dist/components/DataList.es.js +1 -1
  49. package/dist/components/DataPanel.cjs.js +1 -1
  50. package/dist/components/DataPanel.es.js +1 -1
  51. package/dist/components/DateTimePicker.cjs.js +1 -1
  52. package/dist/components/DateTimePicker.cjs.js.map +1 -1
  53. package/dist/components/DateTimePicker.es.js +1 -1
  54. package/dist/components/DateTimePicker.es.js.map +1 -1
  55. package/dist/components/FilterBar.cjs.js +3 -3
  56. package/dist/components/FilterBar.es.js +3 -3
  57. package/dist/components/FormFieldBlocks.cjs.js +1 -1
  58. package/dist/components/FormFieldBlocks.cjs.js.map +1 -1
  59. package/dist/components/FormFieldBlocks.es.js +1 -1
  60. package/dist/components/FormFieldBlocks.es.js.map +1 -1
  61. package/dist/components/MarkdownRenderer.cjs.js +1 -1
  62. package/dist/components/MarkdownRenderer.es.js +1 -1
  63. package/dist/components/MetricsTable.cjs.js +1 -1
  64. package/dist/components/MetricsTable.es.js +1 -1
  65. package/dist/components/PropertyFilter.cjs.js +3 -3
  66. package/dist/components/PropertyFilter.cjs.js.map +1 -1
  67. package/dist/components/PropertyFilter.es.js +3 -3
  68. package/dist/components/PropertyFilter.es.js.map +1 -1
  69. package/dist/components/SavedViews.cjs.js +2 -2
  70. package/dist/components/SavedViews.es.js +2 -2
  71. package/dist/components/Sidebar.cjs.js +8 -8
  72. package/dist/components/Sidebar.cjs.js.map +1 -1
  73. package/dist/components/Sidebar.es.js +9 -9
  74. package/dist/components/Sidebar.es.js.map +1 -1
  75. package/dist/components/ai/activity.cjs.js +1 -1
  76. package/dist/components/ai/activity.es.js +1 -1
  77. package/dist/components/ai/ask-user.cjs.js +1 -1
  78. package/dist/components/ai/ask-user.es.js +1 -1
  79. package/dist/components/ai/plan.cjs.js +1 -1
  80. package/dist/components/ai/plan.es.js +1 -1
  81. package/dist/components/ai/tool-approval.cjs.js +1 -1
  82. package/dist/components/ai/tool-approval.es.js +1 -1
  83. package/dist/components/ai/tool-call.cjs.js +2 -2
  84. package/dist/components/ai/tool-call.es.js +2 -2
  85. package/dist/domains/chat/activity/activity-stretch-line.cjs.js +1 -1
  86. package/dist/domains/chat/activity/activity-stretch-line.es.js +1 -1
  87. package/dist/domains/chat/activity/components/activity-fold.cjs.js +1 -1
  88. package/dist/domains/chat/activity/components/activity-fold.es.js +1 -1
  89. package/dist/domains/chat/activity/components/activity-timed-trigger.cjs.js +1 -1
  90. package/dist/domains/chat/activity/components/activity-timed-trigger.es.js +1 -1
  91. package/dist/domains/chat/activity/components/calls-panel.cjs.js +1 -1
  92. package/dist/domains/chat/activity/components/calls-panel.es.js +1 -1
  93. package/dist/domains/chat/activity/components/stretch-content.cjs.js +1 -1
  94. package/dist/domains/chat/activity/components/stretch-content.es.js +1 -1
  95. package/dist/domains/chat/activity/components/stretch-thought.cjs.js +1 -1
  96. package/dist/domains/chat/activity/components/stretch-thought.es.js +1 -1
  97. package/dist/domains/chat/activity/model/activity-segments.cjs.js +1 -1
  98. package/dist/domains/chat/activity/model/activity-segments.es.js +1 -1
  99. package/dist/domains/chat/activity/model/activity-words.cjs.js +2 -2
  100. package/dist/domains/chat/activity/model/activity-words.es.js +2 -2
  101. package/dist/domains/chat/components/badge-wrapper.cjs.js +1 -1
  102. package/dist/domains/chat/components/badge-wrapper.es.js +1 -1
  103. package/dist/domains/chat/knowledge/knowledge-links.cjs.js +52 -6
  104. package/dist/domains/chat/knowledge/knowledge-links.cjs.js.map +1 -1
  105. package/dist/domains/chat/knowledge/knowledge-links.es.js +53 -9
  106. package/dist/domains/chat/knowledge/knowledge-links.es.js.map +1 -1
  107. package/dist/domains/chat/knowledge/pinned-knowledge-data.cjs.js +10 -3
  108. package/dist/domains/chat/knowledge/pinned-knowledge-data.cjs.js.map +1 -1
  109. package/dist/domains/chat/knowledge/pinned-knowledge-data.es.js +10 -3
  110. package/dist/domains/chat/knowledge/pinned-knowledge-data.es.js.map +1 -1
  111. package/dist/domains/chat/knowledge/pinned-knowledge.cjs.js +8 -3
  112. package/dist/domains/chat/knowledge/pinned-knowledge.cjs.js.map +1 -1
  113. package/dist/domains/chat/knowledge/pinned-knowledge.es.js +8 -3
  114. package/dist/domains/chat/knowledge/pinned-knowledge.es.js.map +1 -1
  115. package/dist/domains/chat/knowledge.cjs.js +2 -0
  116. package/dist/domains/chat/knowledge.es.js +2 -2
  117. package/dist/domains/chat/messages/message-row.cjs.js +3 -3
  118. package/dist/domains/chat/messages/message-row.es.js +3 -3
  119. package/dist/domains/chat/messages/notification-signal-notice.cjs.js +1 -1
  120. package/dist/domains/chat/messages/notification-signal-notice.es.js +1 -1
  121. package/dist/domains/chat/messages/reasoning-content.cjs.js +1 -1
  122. package/dist/domains/chat/messages/reasoning-content.es.js +1 -1
  123. package/dist/domains/chat/messages/renderers/message-text.cjs.js +35 -1
  124. package/dist/domains/chat/messages/renderers/message-text.cjs.js.map +1 -1
  125. package/dist/domains/chat/messages/renderers/message-text.es.js +36 -2
  126. package/dist/domains/chat/messages/renderers/message-text.es.js.map +1 -1
  127. package/dist/domains/chat/messages/renderers/reasoning-part-renderer.cjs.js +1 -1
  128. package/dist/domains/chat/messages/renderers/reasoning-part-renderer.es.js +1 -1
  129. package/dist/domains/chat/messages/signal-badge.cjs.js +1 -1
  130. package/dist/domains/chat/messages/signal-badge.es.js +1 -1
  131. package/dist/domains/chat/messages/skill-message.cjs.js +2 -2
  132. package/dist/domains/chat/messages/skill-message.es.js +2 -2
  133. package/dist/domains/chat/messages/system-reminder-badge.cjs.js +1 -1
  134. package/dist/domains/chat/messages/system-reminder-badge.es.js +1 -1
  135. package/dist/domains/chat/tools/badges/agent-badge-wrapper.cjs.js +1 -1
  136. package/dist/domains/chat/tools/badges/agent-badge-wrapper.es.js +1 -1
  137. package/dist/domains/chat/tools/badges/agent-badge.cjs.js +1 -1
  138. package/dist/domains/chat/tools/badges/agent-badge.es.js +1 -1
  139. package/dist/domains/chat/tools/badges/ask-user-badge.cjs.js +1 -1
  140. package/dist/domains/chat/tools/badges/ask-user-badge.es.js +1 -1
  141. package/dist/domains/chat/tools/badges/file-tree-badge.cjs.js +2 -2
  142. package/dist/domains/chat/tools/badges/file-tree-badge.es.js +2 -2
  143. package/dist/domains/chat/tools/badges/knowledge-body-range.cjs.js +80 -0
  144. package/dist/domains/chat/tools/badges/knowledge-body-range.cjs.js.map +1 -0
  145. package/dist/domains/chat/tools/badges/knowledge-body-range.d.ts +1 -0
  146. package/dist/domains/chat/tools/badges/knowledge-body-range.es.js +78 -0
  147. package/dist/domains/chat/tools/badges/knowledge-body-range.es.js.map +1 -0
  148. package/dist/domains/chat/tools/badges/knowledge-tool-badge.cjs.js +163 -13
  149. package/dist/domains/chat/tools/badges/knowledge-tool-badge.cjs.js.map +1 -1
  150. package/dist/domains/chat/tools/badges/knowledge-tool-badge.es.js +165 -15
  151. package/dist/domains/chat/tools/badges/knowledge-tool-badge.es.js.map +1 -1
  152. package/dist/domains/chat/tools/badges/mcp-input-request-badge.cjs.js +51 -0
  153. package/dist/domains/chat/tools/badges/mcp-input-request-badge.cjs.js.map +1 -0
  154. package/dist/domains/chat/tools/badges/mcp-input-request-badge.d.ts +1 -0
  155. package/dist/domains/chat/tools/badges/mcp-input-request-badge.es.js +49 -0
  156. package/dist/domains/chat/tools/badges/mcp-input-request-badge.es.js.map +1 -0
  157. package/dist/domains/chat/tools/badges/mcp-task-chip.cjs.js +7 -2
  158. package/dist/domains/chat/tools/badges/mcp-task-chip.cjs.js.map +1 -1
  159. package/dist/domains/chat/tools/badges/mcp-task-chip.es.js +7 -2
  160. package/dist/domains/chat/tools/badges/mcp-task-chip.es.js.map +1 -1
  161. package/dist/domains/chat/tools/badges/observation-marker-badge.cjs.js +2 -2
  162. package/dist/domains/chat/tools/badges/observation-marker-badge.es.js +2 -2
  163. package/dist/domains/chat/tools/badges/observation-marker-details.cjs.js +2 -2
  164. package/dist/domains/chat/tools/badges/observation-marker-details.es.js +2 -2
  165. package/dist/domains/chat/tools/badges/observation-renderer.cjs.js +1 -1
  166. package/dist/domains/chat/tools/badges/observation-renderer.es.js +1 -1
  167. package/dist/domains/chat/tools/badges/sandbox-execution-badge.cjs.js +2 -2
  168. package/dist/domains/chat/tools/badges/sandbox-execution-badge.es.js +2 -2
  169. package/dist/domains/chat/tools/badges/tool-approval-badge.cjs.js +1 -1
  170. package/dist/domains/chat/tools/badges/tool-approval-badge.es.js +1 -1
  171. package/dist/domains/chat/tools/badges/tool-badge.cjs.js +9 -4
  172. package/dist/domains/chat/tools/badges/tool-badge.cjs.js.map +1 -1
  173. package/dist/domains/chat/tools/badges/tool-badge.es.js +9 -4
  174. package/dist/domains/chat/tools/badges/tool-badge.es.js.map +1 -1
  175. package/dist/domains/chat/tools/badges/use-deferred-input-request.cjs.js +81 -0
  176. package/dist/domains/chat/tools/badges/use-deferred-input-request.cjs.js.map +1 -0
  177. package/dist/domains/chat/tools/badges/use-deferred-input-request.d.ts +1 -0
  178. package/dist/domains/chat/tools/badges/use-deferred-input-request.es.js +77 -0
  179. package/dist/domains/chat/tools/badges/use-deferred-input-request.es.js.map +1 -0
  180. package/dist/domains/chat/tools/badges/use-mcp-task-progress.cjs.js +11 -2
  181. package/dist/domains/chat/tools/badges/use-mcp-task-progress.cjs.js.map +1 -1
  182. package/dist/domains/chat/tools/badges/use-mcp-task-progress.es.js +11 -2
  183. package/dist/domains/chat/tools/badges/use-mcp-task-progress.es.js.map +1 -1
  184. package/dist/domains/chat/tools/badges/workflow-badge.cjs.js +1 -1
  185. package/dist/domains/chat/tools/badges/workflow-badge.es.js +1 -1
  186. package/dist/domains/chat/tools/mcp-input-request-tool.cjs.js +240 -0
  187. package/dist/domains/chat/tools/mcp-input-request-tool.cjs.js.map +1 -0
  188. package/dist/domains/chat/tools/mcp-input-request-tool.d.ts +1 -0
  189. package/dist/domains/chat/tools/mcp-input-request-tool.es.js +239 -0
  190. package/dist/domains/chat/tools/mcp-input-request-tool.es.js.map +1 -0
  191. package/dist/domains/chat/tools/mcp-input-request.cjs.js +40 -0
  192. package/dist/domains/chat/tools/mcp-input-request.cjs.js.map +1 -0
  193. package/dist/domains/chat/tools/mcp-input-request.d.ts +1 -0
  194. package/dist/domains/chat/tools/mcp-input-request.es.js +33 -0
  195. package/dist/domains/chat/tools/mcp-input-request.es.js.map +1 -0
  196. package/dist/domains/chat/tools/tool-card-kind.cjs.js +8 -3
  197. package/dist/domains/chat/tools/tool-card-kind.cjs.js.map +1 -1
  198. package/dist/domains/chat/tools/tool-card-kind.es.js +8 -4
  199. package/dist/domains/chat/tools/tool-card-kind.es.js.map +1 -1
  200. package/dist/domains/chat/tools/tool-card.cjs.js +1 -1
  201. package/dist/domains/chat/tools/tool-card.es.js +1 -1
  202. package/dist/domains/chat/tools/tool-groups.cjs.js +1 -1
  203. package/dist/domains/chat/tools/tool-groups.es.js +1 -1
  204. package/dist/domains/chat.cjs.js +5 -3
  205. package/dist/domains/chat.es.js +4 -4
  206. package/dist/domains/dashboards/kinds/table/table-view.cjs.js +1 -1
  207. package/dist/domains/dashboards/kinds/table/table-view.es.js +1 -1
  208. package/dist/domains/dashboards/metrics-dashboard.cjs.js +1 -1
  209. package/dist/domains/dashboards/metrics-dashboard.cjs.js.map +1 -1
  210. package/dist/domains/dashboards/metrics-dashboard.es.js +1 -1
  211. package/dist/domains/dashboards/metrics-dashboard.es.js.map +1 -1
  212. package/dist/domains/datasets/components/save-as-dataset-item-dialog.cjs.js +1 -1
  213. package/dist/domains/datasets/components/save-as-dataset-item-dialog.es.js +1 -1
  214. package/dist/domains/knowledge/components/KnowledgePageCard.cjs.js +48 -0
  215. package/dist/domains/knowledge/components/KnowledgePageCard.cjs.js.map +1 -0
  216. package/dist/domains/knowledge/components/KnowledgePageCard.d.ts +1 -0
  217. package/dist/domains/knowledge/components/KnowledgePageCard.es.js +47 -0
  218. package/dist/domains/knowledge/components/KnowledgePageCard.es.js.map +1 -0
  219. package/dist/domains/knowledge/components/KnowledgePageDetail.cjs.js +63 -5
  220. package/dist/domains/knowledge/components/KnowledgePageDetail.cjs.js.map +1 -1
  221. package/dist/domains/knowledge/components/KnowledgePageDetail.es.js +64 -6
  222. package/dist/domains/knowledge/components/KnowledgePageDetail.es.js.map +1 -1
  223. package/dist/domains/knowledge/components/KnowledgePageExplorer.cjs.js +485 -47
  224. package/dist/domains/knowledge/components/KnowledgePageExplorer.cjs.js.map +1 -1
  225. package/dist/domains/knowledge/components/KnowledgePageExplorer.es.js +487 -50
  226. package/dist/domains/knowledge/components/KnowledgePageExplorer.es.js.map +1 -1
  227. package/dist/domains/knowledge/components/KnowledgePageGraph.cjs.js +1051 -123
  228. package/dist/domains/knowledge/components/KnowledgePageGraph.cjs.js.map +1 -1
  229. package/dist/domains/knowledge/components/KnowledgePageGraph.es.js +1054 -126
  230. package/dist/domains/knowledge/components/KnowledgePageGraph.es.js.map +1 -1
  231. package/dist/domains/knowledge/components/KnowledgePageTree.cjs.js +75 -3
  232. package/dist/domains/knowledge/components/KnowledgePageTree.cjs.js.map +1 -1
  233. package/dist/domains/knowledge/components/KnowledgePageTree.es.js +76 -4
  234. package/dist/domains/knowledge/components/KnowledgePageTree.es.js.map +1 -1
  235. package/dist/domains/knowledge/lib/circleText.cjs.js +9 -0
  236. package/dist/domains/knowledge/lib/circleText.cjs.js.map +1 -0
  237. package/dist/domains/knowledge/lib/circleText.d.ts +1 -0
  238. package/dist/domains/knowledge/lib/circleText.es.js +8 -0
  239. package/dist/domains/knowledge/lib/circleText.es.js.map +1 -0
  240. package/dist/domains/knowledge/lib/fitViewport.cjs.js +82 -0
  241. package/dist/domains/knowledge/lib/fitViewport.cjs.js.map +1 -0
  242. package/dist/domains/knowledge/lib/fitViewport.d.ts +1 -0
  243. package/dist/domains/knowledge/lib/fitViewport.es.js +73 -0
  244. package/dist/domains/knowledge/lib/fitViewport.es.js.map +1 -0
  245. package/dist/domains/knowledge/lib/graphShape.cjs.js +524 -0
  246. package/dist/domains/knowledge/lib/graphShape.cjs.js.map +1 -0
  247. package/dist/domains/knowledge/lib/graphShape.d.ts +1 -0
  248. package/dist/domains/knowledge/lib/graphShape.es.js +499 -0
  249. package/dist/domains/knowledge/lib/graphShape.es.js.map +1 -0
  250. package/dist/domains/knowledge/lib/linkCountsText.cjs.js +11 -0
  251. package/dist/domains/knowledge/lib/linkCountsText.cjs.js.map +1 -0
  252. package/dist/domains/knowledge/lib/linkCountsText.d.ts +1 -0
  253. package/dist/domains/knowledge/lib/linkCountsText.es.js +10 -0
  254. package/dist/domains/knowledge/lib/linkCountsText.es.js.map +1 -0
  255. package/dist/domains/knowledge/lib/pageAddress.cjs.js +29 -0
  256. package/dist/domains/knowledge/lib/pageAddress.cjs.js.map +1 -0
  257. package/dist/domains/knowledge/lib/pageAddress.d.ts +1 -0
  258. package/dist/domains/knowledge/lib/pageAddress.es.js +27 -0
  259. package/dist/domains/knowledge/lib/pageAddress.es.js.map +1 -0
  260. package/dist/domains/knowledge/lib/pageGraph.cjs.js +11 -11
  261. package/dist/domains/knowledge/lib/pageGraph.cjs.js.map +1 -1
  262. package/dist/domains/knowledge/lib/pageGraph.es.js +11 -11
  263. package/dist/domains/knowledge/lib/pageGraph.es.js.map +1 -1
  264. package/dist/domains/knowledge/lib/pageRefs.cjs.js +69 -0
  265. package/dist/domains/knowledge/lib/pageRefs.cjs.js.map +1 -0
  266. package/dist/domains/knowledge/lib/pageRefs.d.ts +1 -0
  267. package/dist/domains/knowledge/lib/pageRefs.es.js +66 -0
  268. package/dist/domains/knowledge/lib/pageRefs.es.js.map +1 -0
  269. package/dist/domains/knowledge/lib/pageTree.cjs.js +5 -0
  270. package/dist/domains/knowledge/lib/pageTree.cjs.js.map +1 -1
  271. package/dist/domains/knowledge/lib/pageTree.es.js +5 -1
  272. package/dist/domains/knowledge/lib/pageTree.es.js.map +1 -1
  273. package/dist/domains/knowledge/lib/remarkKnowledgeLinks.cjs.js +82 -0
  274. package/dist/domains/knowledge/lib/remarkKnowledgeLinks.cjs.js.map +1 -0
  275. package/dist/domains/knowledge/lib/remarkKnowledgeLinks.d.ts +1 -0
  276. package/dist/domains/knowledge/lib/remarkKnowledgeLinks.es.js +78 -0
  277. package/dist/domains/knowledge/lib/remarkKnowledgeLinks.es.js.map +1 -0
  278. package/dist/domains/knowledge/lib/tooltipSide.cjs.js +77 -0
  279. package/dist/domains/knowledge/lib/tooltipSide.cjs.js.map +1 -0
  280. package/dist/domains/knowledge/lib/tooltipSide.d.ts +1 -0
  281. package/dist/domains/knowledge/lib/tooltipSide.es.js +75 -0
  282. package/dist/domains/knowledge/lib/tooltipSide.es.js.map +1 -0
  283. package/dist/domains/knowledge/lib/useLeavingNodes.cjs.js +65 -0
  284. package/dist/domains/knowledge/lib/useLeavingNodes.cjs.js.map +1 -0
  285. package/dist/domains/knowledge/lib/useLeavingNodes.d.ts +1 -0
  286. package/dist/domains/knowledge/lib/useLeavingNodes.es.js +62 -0
  287. package/dist/domains/knowledge/lib/useLeavingNodes.es.js.map +1 -0
  288. package/dist/domains/knowledge/lib/useStableWhile.cjs.js +15 -0
  289. package/dist/domains/knowledge/lib/useStableWhile.cjs.js.map +1 -0
  290. package/dist/domains/knowledge/lib/useStableWhile.d.ts +1 -0
  291. package/dist/domains/knowledge/lib/useStableWhile.es.js +14 -0
  292. package/dist/domains/knowledge/lib/useStableWhile.es.js.map +1 -0
  293. package/dist/domains/logs/components/log-data-panel.cjs.js +1 -1
  294. package/dist/domains/logs/components/log-data-panel.es.js +1 -1
  295. package/dist/domains/logs/components/logs-saved-views.cjs.js +1 -1
  296. package/dist/domains/logs/components/logs-saved-views.es.js +1 -1
  297. package/dist/domains/logs/components/logs-toolbar.cjs.js +1 -1
  298. package/dist/domains/logs/components/logs-toolbar.es.js +1 -1
  299. package/dist/domains/metrics/components/breakdown/breakdown-table.cjs.js +2 -2
  300. package/dist/domains/metrics/components/breakdown/breakdown-table.cjs.js.map +1 -1
  301. package/dist/domains/metrics/components/breakdown/breakdown-table.es.js +2 -2
  302. package/dist/domains/metrics/components/breakdown/breakdown-table.es.js.map +1 -1
  303. package/dist/domains/metrics/components/metrics-time-range-chip.cjs.js +1 -1
  304. package/dist/domains/metrics/components/metrics-time-range-chip.es.js +1 -1
  305. package/dist/domains/observability/saved-views/observability-saved-views.cjs.js +1 -1
  306. package/dist/domains/observability/saved-views/observability-saved-views.es.js +1 -1
  307. package/dist/domains/observability/saved-views.cjs.js +1 -1
  308. package/dist/domains/observability/saved-views.es.js +1 -1
  309. package/dist/domains/observability.cjs.js +1 -1
  310. package/dist/domains/observability.es.js +1 -1
  311. package/dist/domains/scores/components/score-data-panel.cjs.js +1 -1
  312. package/dist/domains/scores/components/score-data-panel.es.js +1 -1
  313. package/dist/domains/scores/components/span-scoring.cjs.js +3 -3
  314. package/dist/domains/scores/components/span-scoring.cjs.js.map +1 -1
  315. package/dist/domains/scores/components/span-scoring.es.js +3 -3
  316. package/dist/domains/scores/components/span-scoring.es.js.map +1 -1
  317. package/dist/domains/scores/components/trace-scores-list.cjs.js +2 -2
  318. package/dist/domains/scores/components/trace-scores-list.es.js +2 -2
  319. package/dist/domains/skills/skill-simple-form.cjs.js +2 -2
  320. package/dist/domains/skills/skill-simple-form.cjs.js.map +1 -1
  321. package/dist/domains/skills/skill-simple-form.es.js +2 -2
  322. package/dist/domains/skills/skill-simple-form.es.js.map +1 -1
  323. package/dist/domains/spans/components/spans-explorer-body.cjs.js +1 -1
  324. package/dist/domains/spans/components/spans-explorer-body.es.js +1 -1
  325. package/dist/domains/spans/components/spans-filter-bar.cjs.js +3 -3
  326. package/dist/domains/spans/components/spans-filter-bar.cjs.js.map +1 -1
  327. package/dist/domains/spans/components/spans-filter-bar.es.js +3 -3
  328. package/dist/domains/spans/components/spans-filter-bar.es.js.map +1 -1
  329. package/dist/domains/spans/hooks/use-spans-filter-bar.cjs.js +1 -1
  330. package/dist/domains/spans/hooks/use-spans-filter-bar.es.js +1 -1
  331. package/dist/domains/threads/components/threads-explorer-body.cjs.js +1 -1
  332. package/dist/domains/threads/components/threads-explorer-body.es.js +1 -1
  333. package/dist/domains/threads/components/threads-filter-bar.cjs.js +3 -3
  334. package/dist/domains/threads/components/threads-filter-bar.cjs.js.map +1 -1
  335. package/dist/domains/threads/components/threads-filter-bar.es.js +3 -3
  336. package/dist/domains/threads/components/threads-filter-bar.es.js.map +1 -1
  337. package/dist/domains/threads/hooks/use-threads-filter-bar.cjs.js +1 -1
  338. package/dist/domains/threads/hooks/use-threads-filter-bar.es.js +1 -1
  339. package/dist/domains/traces/components/feedback-thread.cjs.js +1 -1
  340. package/dist/domains/traces/components/feedback-thread.cjs.js.map +1 -1
  341. package/dist/domains/traces/components/feedback-thread.es.js +1 -1
  342. package/dist/domains/traces/components/feedback-thread.es.js.map +1 -1
  343. package/dist/domains/traces/components/span-data-panel-view.cjs.js +1 -1
  344. package/dist/domains/traces/components/span-data-panel-view.es.js +1 -1
  345. package/dist/domains/traces/components/span-payload/span-error-renderer.cjs.js +1 -1
  346. package/dist/domains/traces/components/span-payload/span-error-renderer.es.js +1 -1
  347. package/dist/domains/traces/components/span-payload/span-input-renderers.cjs.js +1 -1
  348. package/dist/domains/traces/components/span-payload/span-input-renderers.es.js +1 -1
  349. package/dist/domains/traces/components/span-payload/span-output-renderers.cjs.js +2 -2
  350. package/dist/domains/traces/components/span-payload/span-output-renderers.es.js +2 -2
  351. package/dist/domains/traces/components/span-payload/span-payload-messages.cjs.js +2 -2
  352. package/dist/domains/traces/components/span-payload/span-payload-messages.es.js +2 -2
  353. package/dist/domains/traces/components/span-payload/span-payload-primitives.cjs.js +1 -1
  354. package/dist/domains/traces/components/span-payload/span-payload-primitives.es.js +1 -1
  355. package/dist/domains/traces/components/span-payload/span-payload-processor.cjs.js +1 -1
  356. package/dist/domains/traces/components/span-payload/span-payload-processor.es.js +1 -1
  357. package/dist/domains/traces/components/span-payload/span-payload-tool.cjs.js +1 -1
  358. package/dist/domains/traces/components/span-payload/span-payload-tool.es.js +1 -1
  359. package/dist/domains/traces/components/span-payload/span-processor-mutations.cjs.js +1 -1
  360. package/dist/domains/traces/components/span-payload/span-processor-mutations.es.js +1 -1
  361. package/dist/domains/traces/components/span-payload/span-tools-section.cjs.js +1 -1
  362. package/dist/domains/traces/components/span-payload/span-tools-section.es.js +1 -1
  363. package/dist/domains/traces/components/span-summary-description.cjs.js +1 -1
  364. package/dist/domains/traces/components/span-summary-description.es.js +1 -1
  365. package/dist/domains/traces/components/span-timeline-row.cjs.js +1 -1
  366. package/dist/domains/traces/components/span-timeline-row.es.js +1 -1
  367. package/dist/domains/traces/components/span-timing-hover-card.cjs.js +1 -1
  368. package/dist/domains/traces/components/span-timing-hover-card.es.js +1 -1
  369. package/dist/domains/traces/components/thread-trace/thread-trace-details.cjs.js +1 -1
  370. package/dist/domains/traces/components/thread-trace/thread-trace-details.es.js +1 -1
  371. package/dist/domains/traces/components/trace-columns-menu.cjs.js +3 -3
  372. package/dist/domains/traces/components/trace-columns-menu.cjs.js.map +1 -1
  373. package/dist/domains/traces/components/trace-columns-menu.es.js +3 -3
  374. package/dist/domains/traces/components/trace-columns-menu.es.js.map +1 -1
  375. package/dist/domains/traces/components/trace-data-panel-view.cjs.js +10 -4
  376. package/dist/domains/traces/components/trace-data-panel-view.cjs.js.map +1 -1
  377. package/dist/domains/traces/components/trace-data-panel-view.es.js +10 -4
  378. package/dist/domains/traces/components/trace-data-panel-view.es.js.map +1 -1
  379. package/dist/domains/traces/components/trace-error-cell.cjs.js +1 -1
  380. package/dist/domains/traces/components/trace-error-cell.es.js +1 -1
  381. package/dist/domains/traces/components/trace-id-button.cjs.js +1 -1
  382. package/dist/domains/traces/components/trace-id-button.es.js +1 -1
  383. package/dist/domains/traces/components/trace-summary-description.cjs.js +1 -1
  384. package/dist/domains/traces/components/trace-summary-description.es.js +1 -1
  385. package/dist/domains/traces/components/trace-thread-panel.cjs.js +1 -1
  386. package/dist/domains/traces/components/trace-thread-panel.es.js +1 -1
  387. package/dist/domains/traces/components/traces-explorer/traces-explorer-filter-bar.cjs.js +3 -3
  388. package/dist/domains/traces/components/traces-explorer/traces-explorer-filter-bar.cjs.js.map +1 -1
  389. package/dist/domains/traces/components/traces-explorer/traces-explorer-filter-bar.es.js +3 -3
  390. package/dist/domains/traces/components/traces-explorer/traces-explorer-filter-bar.es.js.map +1 -1
  391. package/dist/domains/traces/components/traces-explorer/traces-explorer-saved-views.cjs.js +1 -1
  392. package/dist/domains/traces/components/traces-explorer/traces-explorer-saved-views.es.js +1 -1
  393. package/dist/domains/traces/components/traces-explorer/use-traces-filter-bar.cjs.js +1 -1
  394. package/dist/domains/traces/components/traces-explorer/use-traces-filter-bar.es.js +1 -1
  395. package/dist/domains/workflows/components/workflow-combobox.cjs.js +2 -2
  396. package/dist/domains/workflows/components/workflow-combobox.cjs.js.map +1 -1
  397. package/dist/domains/workflows/components/workflow-combobox.es.js +2 -2
  398. package/dist/domains/workflows/components/workflow-combobox.es.js.map +1 -1
  399. package/dist/domains/workflows/runs/workflow-run-list.cjs.js +1 -1
  400. package/dist/domains/workflows/runs/workflow-run-list.es.js +1 -1
  401. package/dist/domains/workflows/workflow/input/workflow-processor-input.cjs.js +3 -3
  402. package/dist/domains/workflows/workflow/input/workflow-processor-input.cjs.js.map +1 -1
  403. package/dist/domains/workflows/workflow/input/workflow-processor-input.es.js +3 -3
  404. package/dist/domains/workflows/workflow/input/workflow-processor-input.es.js.map +1 -1
  405. package/dist/domains/workflows/workflow/use-workflow-trigger.cjs.js +3 -3
  406. package/dist/domains/workflows/workflow/use-workflow-trigger.es.js +3 -3
  407. package/dist/domains/workflows/workflow/workflow-input-data.cjs.js +1 -1
  408. package/dist/domains/workflows/workflow/workflow-input-data.es.js +1 -1
  409. package/dist/domains/workflows/workflow/workflow-suspended-steps.cjs.js +2 -2
  410. package/dist/domains/workflows/workflow/workflow-suspended-steps.es.js +2 -2
  411. package/dist/domains/workflows/workflow/workflow-time-travel-form.cjs.js +2 -2
  412. package/dist/domains/workflows/workflow/workflow-time-travel-form.es.js +2 -2
  413. package/dist/domains/workspace/components/workspace-add-skill-dialog.cjs.js +2 -2
  414. package/dist/domains/workspace/components/workspace-add-skill-dialog.cjs.js.map +1 -1
  415. package/dist/domains/workspace/components/workspace-add-skill-dialog.es.js +2 -2
  416. package/dist/domains/workspace/components/workspace-add-skill-dialog.es.js.map +1 -1
  417. package/dist/domains/workspace/components/workspace-markdown-preview.cjs.js +1 -1
  418. package/dist/domains/workspace/components/workspace-markdown-preview.es.js +1 -1
  419. package/dist/{filter-bar-chip-B4sV4gDm.js → filter-bar-chip-CABeKrtf.js} +4 -4
  420. package/dist/{filter-bar-chip-B4sV4gDm.js.map → filter-bar-chip-CABeKrtf.js.map} +1 -1
  421. package/dist/{filter-bar-chip-CIEsWcEw.cjs → filter-bar-chip-Cg-UbIwP.cjs} +4 -4
  422. package/dist/{filter-bar-chip-CIEsWcEw.cjs.map → filter-bar-chip-Cg-UbIwP.cjs.map} +1 -1
  423. package/dist/{filter-bar-time-range-DvuaFnkI.cjs → filter-bar-time-range-BA-pXMlo.cjs} +2 -2
  424. package/dist/{filter-bar-time-range-DvuaFnkI.cjs.map → filter-bar-time-range-BA-pXMlo.cjs.map} +1 -1
  425. package/dist/{filter-bar-time-range-CXQMBgpz.js → filter-bar-time-range-mg9JeYue.js} +2 -2
  426. package/dist/{filter-bar-time-range-CXQMBgpz.js.map → filter-bar-time-range-mg9JeYue.js.map} +1 -1
  427. package/dist/layout/tabbed-container.cjs.js +1 -1
  428. package/dist/layout/tabbed-container.es.js +1 -1
  429. package/dist/lib/form/dynamic-form.cjs.js +2 -2
  430. package/dist/lib/form/dynamic-form.es.js +2 -2
  431. package/dist/lib/form/json-draft.cjs.js +1 -1
  432. package/dist/lib/form/json-draft.es.js +1 -1
  433. package/dist/lib/form/zod-provider.cjs.js +1 -1
  434. package/dist/lib/form/zod-provider.es.js +1 -1
  435. package/dist/{observability-saved-views-BBam8Fr5.js → observability-saved-views-CjKTEp1V.js} +3 -3
  436. package/dist/observability-saved-views-CjKTEp1V.js.map +1 -0
  437. package/dist/{observability-saved-views-BAzxxoAr.cjs → observability-saved-views-Daizz4tU.cjs} +3 -3
  438. package/dist/observability-saved-views-Daizz4tU.cjs.map +1 -0
  439. package/dist/primitives/chart-plot.cjs.js +8 -6
  440. package/dist/primitives/chart-plot.cjs.js.map +1 -1
  441. package/dist/primitives/chart-plot.es.js +8 -6
  442. package/dist/primitives/chart-plot.es.js.map +1 -1
  443. package/dist/primitives/control-icon.cjs.js.map +1 -1
  444. package/dist/primitives/control-icon.es.js.map +1 -1
  445. package/dist/{property-filter-applied-p3dTTDdb.js → property-filter-applied--U5EZdaA.js} +2 -2
  446. package/dist/property-filter-applied--U5EZdaA.js.map +1 -0
  447. package/dist/{property-filter-applied-BCeRLcXb.cjs → property-filter-applied-BkkIObRq.cjs} +2 -2
  448. package/dist/property-filter-applied-BkkIObRq.cjs.map +1 -0
  449. package/dist/{span-payload-primitives-B3RdahsC.js → span-payload-primitives-CKKIAVPJ.js} +4 -4
  450. package/dist/{span-payload-primitives-B3RdahsC.js.map → span-payload-primitives-CKKIAVPJ.js.map} +1 -1
  451. package/dist/{span-payload-primitives-_2d-pAOD.cjs → span-payload-primitives-D4tHWN2W.cjs} +4 -4
  452. package/dist/{span-payload-primitives-_2d-pAOD.cjs.map → span-payload-primitives-D4tHWN2W.cjs.map} +1 -1
  453. package/dist/src/domains/chat/knowledge/knowledge-links.d.ts +32 -4
  454. package/dist/src/domains/chat/knowledge/pinned-knowledge-data.d.ts +2 -0
  455. package/dist/src/domains/chat/tools/badges/knowledge-body-range.d.ts +12 -0
  456. package/dist/src/domains/chat/tools/badges/knowledge-tool-badge.d.ts +5 -2
  457. package/dist/src/domains/chat/tools/badges/mcp-input-request-badge.d.ts +18 -0
  458. package/dist/src/domains/chat/tools/badges/tool-badge.d.ts +4 -1
  459. package/dist/src/domains/chat/tools/badges/use-deferred-input-request.d.ts +44 -0
  460. package/dist/src/domains/chat/tools/badges/use-mcp-task-progress.d.ts +6 -1
  461. package/dist/src/domains/chat/tools/mcp-input-request-tool.d.ts +18 -0
  462. package/dist/src/domains/chat/tools/mcp-input-request.d.ts +40 -0
  463. package/dist/src/domains/chat/tools/tool-card-kind.d.ts +4 -2
  464. package/dist/src/domains/chat/tools/tool-card.d.ts +1 -1
  465. package/dist/src/domains/knowledge/components/KnowledgePageCard.d.ts +23 -0
  466. package/dist/src/domains/knowledge/components/KnowledgePageExplorer.d.ts +29 -0
  467. package/dist/src/domains/knowledge/components/KnowledgePageGraph.d.ts +27 -1
  468. package/dist/src/domains/knowledge/components/KnowledgePageTree.d.ts +2 -1
  469. package/dist/src/domains/knowledge/lib/circleText.d.ts +2 -0
  470. package/dist/src/domains/knowledge/lib/fitViewport.d.ts +67 -0
  471. package/dist/src/domains/knowledge/lib/graphShape.d.ts +131 -0
  472. package/dist/src/domains/knowledge/lib/linkCountsText.d.ts +5 -0
  473. package/dist/src/domains/knowledge/lib/pageAddress.d.ts +5 -0
  474. package/dist/src/domains/knowledge/lib/pageGraph.d.ts +4 -4
  475. package/dist/src/domains/knowledge/lib/pageRefs.d.ts +15 -0
  476. package/dist/src/domains/knowledge/lib/pageTree.d.ts +2 -0
  477. package/dist/src/domains/knowledge/lib/remarkKnowledgeLinks.d.ts +13 -0
  478. package/dist/src/domains/knowledge/lib/tooltipSide.d.ts +40 -0
  479. package/dist/src/domains/knowledge/lib/useLeavingNodes.d.ts +14 -0
  480. package/dist/src/domains/knowledge/lib/useStableWhile.d.ts +5 -0
  481. package/dist/src/domains/knowledge/pageTypes.d.ts +6 -1
  482. package/dist/src/ds/components/MarkdownRenderer/markdown-renderer.d.ts +8 -1
  483. package/dist/src/ds/components/MetricsTable/metrics-table-rows.d.ts +10 -3
  484. package/dist/src/ds/components/MetricsTable/metrics-table.d.ts +1 -1
  485. package/dist/src/ds/components/ai/tool-call/tool-phrases.d.ts +6 -0
  486. package/dist/style.css +83 -3
  487. package/dist/{tabbed-container-DQU7pVio.cjs → tabbed-container-B4lCBgRP.cjs} +2 -2
  488. package/dist/{tabbed-container-DQU7pVio.cjs.map → tabbed-container-B4lCBgRP.cjs.map} +1 -1
  489. package/dist/{tabbed-container-5j6dhoRX.js → tabbed-container-DI1GI1Qv.js} +2 -2
  490. package/dist/{tabbed-container-5j6dhoRX.js.map → tabbed-container-DI1GI1Qv.js.map} +1 -1
  491. package/dist/{tool-approval-1qiB4hhG.cjs → tool-approval-CJvPDL7D.cjs} +4 -4
  492. package/dist/{tool-approval-1qiB4hhG.cjs.map → tool-approval-CJvPDL7D.cjs.map} +1 -1
  493. package/dist/{tool-approval-B6MFcaKV.js → tool-approval-DyN11vFA.js} +4 -4
  494. package/dist/{tool-approval-B6MFcaKV.js.map → tool-approval-DyN11vFA.js.map} +1 -1
  495. package/dist/{tool-call-Bu66PkD-.cjs → tool-call-DBn14X-3.cjs} +9 -3
  496. package/dist/{tool-call-Bu66PkD-.cjs.map → tool-call-DBn14X-3.cjs.map} +1 -1
  497. package/dist/{tool-call-Ch9-jjXU.js → tool-call-Dsj43lvJ.js} +9 -3
  498. package/dist/{tool-call-Ch9-jjXU.js.map → tool-call-Dsj43lvJ.js.map} +1 -1
  499. package/dist/{tool-card-DrqPZfPQ.cjs → tool-card-rxhTDpk_.cjs} +164 -126
  500. package/dist/tool-card-rxhTDpk_.cjs.map +1 -0
  501. package/dist/{tool-card-sO6P2Qj4.js → tool-card-toDgoZzJ.js} +165 -127
  502. package/dist/tool-card-toDgoZzJ.js.map +1 -0
  503. package/dist/{tool-presentation-DvCsb_kz.js → tool-presentation-CvibOP1J.js} +6 -1
  504. package/dist/tool-presentation-CvibOP1J.js.map +1 -0
  505. package/dist/{tool-presentation-CQlDEwgS.cjs → tool-presentation-D6nzVruN.cjs} +6 -1
  506. package/dist/tool-presentation-D6nzVruN.cjs.map +1 -0
  507. package/oxlint/index.js +90 -0
  508. package/package.json +9 -9
  509. package/theme.css +4 -3
  510. package/dist/DataCodeSection-CcPmJPTp.cjs.map +0 -1
  511. package/dist/DataCodeSection-KJRyRD1Q.js.map +0 -1
  512. package/dist/FilterBar-BO-vvvyq.js.map +0 -1
  513. package/dist/FilterBar-Buw0tv51.cjs.map +0 -1
  514. package/dist/MarkdownRenderer-2GOXQJEv.js.map +0 -1
  515. package/dist/MarkdownRenderer-CB8Z_CHc.cjs.map +0 -1
  516. package/dist/MetricsTable-CRPeLHe1.js.map +0 -1
  517. package/dist/MetricsTable-D-aZf3dk.cjs.map +0 -1
  518. package/dist/ask-user-B225wzWc.js.map +0 -1
  519. package/dist/ask-user-DdYz56qH.cjs.map +0 -1
  520. package/dist/combobox-CMx2ayFN.cjs.map +0 -1
  521. package/dist/combobox-parts-C1CugUAU.js.map +0 -1
  522. package/dist/combobox-parts-ScKcYjMR.cjs.map +0 -1
  523. package/dist/domains/knowledge/lib/pageLayout.cjs.js +0 -49
  524. package/dist/domains/knowledge/lib/pageLayout.cjs.js.map +0 -1
  525. package/dist/domains/knowledge/lib/pageLayout.d.ts +0 -1
  526. package/dist/domains/knowledge/lib/pageLayout.es.js +0 -48
  527. package/dist/domains/knowledge/lib/pageLayout.es.js.map +0 -1
  528. package/dist/observability-saved-views-BAzxxoAr.cjs.map +0 -1
  529. package/dist/observability-saved-views-BBam8Fr5.js.map +0 -1
  530. package/dist/property-filter-applied-BCeRLcXb.cjs.map +0 -1
  531. package/dist/property-filter-applied-p3dTTDdb.js.map +0 -1
  532. package/dist/src/domains/knowledge/lib/pageLayout.d.ts +0 -24
  533. package/dist/tool-card-DrqPZfPQ.cjs.map +0 -1
  534. package/dist/tool-card-sO6P2Qj4.js.map +0 -1
  535. package/dist/tool-presentation-CQlDEwgS.cjs.map +0 -1
  536. package/dist/tool-presentation-DvCsb_kz.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FilterBar-BgW2dqRQ.js","names":["_Fragment","_Fragment"],"sources":["../src/ds/components/FilterBar/filter-bar-input.tsx","../src/ds/components/FilterBar/use-settle-on-leave.ts","../src/ds/components/FilterBar/filter-bar-group-editor.tsx","../src/ds/components/FilterBar/filter-bar-advanced-chip.tsx","../src/ds/components/FilterBar/filter-bar-clear.tsx","../src/ds/components/FilterBar/filter-bar.tsx","../src/ds/components/FilterBar/default-operators.ts"],"sourcesContent":["import type { BaseUIEvent } from '@base-ui/react/types';\nimport { BracesIcon, ListFilterIcon } from 'lucide-react';\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport type { KeyboardEvent } from 'react';\nimport { flushSync } from 'react-dom';\nimport { FILTER_BAR_CONTROL_SIZE, FilterBarFieldLabel, alwaysHighlightProps } from './filter-bar-chip';\nimport { useFilterBarContext } from './filter-bar-context';\nimport { FilterBarOptionLabel, FilterBarOptionList } from './filter-bar-option-list';\nimport { findGroup } from './filter-bar-tree';\nimport { matchesQueryFilter } from './match-query';\nimport type { FilterBarDraft, FilterBarField, FilterBarOperator, FilterBarOption, FilterBarValue } from './types';\nimport { parseFieldValue } from './types';\nimport { useValueStep } from './use-value-step';\nimport { Button } from '@/ds/components/Button/Button';\nimport { ComboboxPrimitive, comboboxStyles } from '@/ds/components/Combobox';\nimport { comboboxTriggerClass } from '@/ds/components/Combobox/combobox-styles';\nimport { Kbd } from '@/ds/components/Kbd/kbd';\nimport { Txt } from '@/ds/components/Txt';\nimport { FLOATING_POSITION_METHOD } from '@/ds/primitives/floating';\nimport { inputFocusBorderWithin, unstyledFormElementStyle } from '@/ds/primitives/form-element';\nimport { MENU_SIDE_OFFSET } from '@/ds/primitives/menu-item';\nimport { passwordManagerOptOutProps } from '@/ds/primitives/password-manager-autofill';\nimport { usePortalContainer } from '@/ds/primitives/portal-container';\nimport { useIsApplePlatform } from '@/hooks/use-keyboard-shortcut-label';\nimport { cn } from '@/lib/utils';\n\ntype Step = 'field' | 'operator' | 'value';\n\ntype Item = FilterBarField | FilterBarOperator | FilterBarOption;\n\nconst getItemLabel = (item: Item) => ('label' in item && item.label ? item.label : 'value' in item ? item.value : '');\n\nconst EMPTY_ITEMS: readonly Item[] = [];\n/** Pinned last entry of the field list that spawns an advanced filter (an `or` group) instead of a filter. */\nconst ADVANCED_FIELD_ID = '__filter-bar-advanced__';\nconst ADVANCED_FIELD: FilterBarField = {\n id: ADVANCED_FIELD_ID,\n label: 'Advanced filter…',\n icon: BracesIcon,\n operators: [],\n};\n\nexport type FilterBarInputProps = {\n placeholder?: string;\n className?: string;\n 'aria-label'?: string;\n /**\n * Group this instance commits into; omit for the bar's own input. Only the instance whose\n * `groupId` matches the provider's `inputTarget` renders, so a single input is ever mounted.\n */\n groupId?: string;\n /** Called when Escape is pressed on an empty query inside a group, after the input hands back to the bar. */\n onLeave?: () => void;\n};\n\n/**\n * Typeahead entry point: type to pick a field, then an operator, then a value.\n * Focus never leaves the input; the popup is driven with the arrow keys.\n */\nexport function FilterBarInput(props: FilterBarInputProps) {\n const ctx = useFilterBarContext();\n if (ctx.inputTarget !== props.groupId) return null;\n return <FilterBarInputImpl {...props} />;\n}\n\nfunction FilterBarInputImpl({\n placeholder = 'Filter',\n className,\n 'aria-label': ariaLabel = 'Add filter',\n groupId,\n onLeave,\n}: FilterBarInputProps) {\n const ctx = useFilterBarContext();\n const container = usePortalContainer();\n const inputRef = useRef<HTMLInputElement | null>(null);\n const anchorRef = useRef<HTMLDivElement>(null);\n const [open, setOpen] = useState(false);\n const [query, setQuery] = useState('');\n const [highlighted, setHighlighted] = useState<Item | null>(null);\n const [emptyForStepChange, setEmptyForStepChange] = useState(false);\n const modEnterLabel = useIsApplePlatform() ? '⌘↵' : 'Ctrl ↵';\n\n // The draft lives in the provider so the chip list can render it; the step follows from it.\n const { draft, setDraft: setDraftState, commitDraft } = ctx;\n const step: Step = !draft ? 'field' : !draft.operatorId ? 'operator' : 'value';\n const field = draft ? ctx.getField(draft.fieldId) : undefined;\n const fieldOperators = useMemo(() => (field ? ctx.getFieldOperators(field) : []), [ctx, field]);\n const operator = draft?.operatorId\n ? (fieldOperators.find(o => o.id === draft.operatorId) ?? ctx.getOperator(draft.operatorId))\n : undefined;\n // The advanced option lives in the bar only; inside a popover, nesting is the editor's `+ Group`.\n const offerAdvanced = ctx.groupsEnabled && groupId === undefined;\n const visibleFields = useMemo(() => {\n const fields = ctx.fields.filter(f => !f.hidden);\n return offerAdvanced ? [...fields, ADVANCED_FIELD] : fields;\n }, [ctx.fields, offerAdvanced]);\n const targetGroup = groupId ? findGroup(ctx.expression, groupId) : undefined;\n\n // A group's input mounts on demand (see `openGroupInput`) and takes focus itself.\n useEffect(() => {\n if (groupId) inputRef.current?.focus();\n }, [groupId]);\n\n // Base UI owns the highlight index and keeps it when the list content changes, so a row\n // reached with ArrowDown would carry over into the step that follows. An empty list committed\n // first drops that index, and `autoHighlight` re-anchors on the first row of the new step.\n const withHighlightReset = useCallback((change: () => void) => {\n flushSync(() => setEmptyForStepChange(true));\n change();\n setEmptyForStepChange(false);\n }, []);\n\n const setDraft = useCallback(\n (next: Omit<FilterBarDraft, 'id' | 'from'> | null) => withHighlightReset(() => setDraftState(next)),\n [withHighlightReset, setDraftState],\n );\n\n const reset = useCallback(() => {\n setDraftState(null);\n setQuery('');\n }, [setDraftState]);\n\n const close = useCallback(() => {\n setOpen(false);\n reset();\n }, [reset]);\n\n const commit = useCallback(\n (fieldId: string, operatorId: string, value: FilterBarValue) => {\n withHighlightReset(() => commitDraft({ fieldId, operatorId }, value));\n setQuery('');\n inputRef.current?.focus();\n },\n [withHighlightReset, commitDraft],\n );\n\n const selectOperator = useCallback(\n (fieldId: string, next: FilterBarOperator) => {\n if (next.arity === 'none') {\n commit(fieldId, next.id, '');\n return;\n }\n setDraft({ fieldId, operatorId: next.id });\n setQuery('');\n },\n [commit, setDraft],\n );\n\n const selectField = useCallback(\n (next: FilterBarField) => {\n if (next.id === ADVANCED_FIELD_ID) {\n // `or` is the useful default: an `and` group is indistinguishable from the root.\n const id = ctx.addGroup(undefined, 'or');\n ctx.setOpenGroup(id);\n ctx.openGroupInput(id);\n setQuery('');\n setOpen(false);\n return;\n }\n const [only, ...rest] = ctx.getFieldOperators(next);\n // Free-text entry with text already typed: that text is the value, so neither the\n // operator nor the value step has anything left to ask.\n if (next.search && only && query.trim() !== '') {\n commit(next.id, only.id, parseFieldValue(next.type, query));\n return;\n }\n // A single allowed operator is implied: skip straight to the value step.\n if (only && rest.length === 0) {\n selectOperator(next.id, only);\n return;\n }\n setDraft({ fieldId: next.id });\n setQuery('');\n },\n [ctx, commit, query, selectOperator, setDraft],\n );\n\n const valueStep = useValueStep({\n field,\n operator,\n query,\n enabled: open && step === 'value',\n setQuery,\n onCommit: value => {\n if (draft?.operatorId) commit(draft.fieldId, draft.operatorId, value);\n },\n });\n\n // Leaving a group's input hands the target back to the bar; empty groups are pruned when the\n // popover closes, never here.\n const leaveGroup = useCallback(() => {\n if (!groupId) return false;\n ctx.openGroupInput(undefined);\n onLeave?.();\n return true;\n }, [ctx, groupId, onLeave]);\n\n const stepBack = useCallback(() => {\n if (step === 'value' && draft) {\n // Back to the field step when the operator was implied (single operator).\n const skipOperator = field ? fieldOperators.length === 1 : false;\n setDraft(skipOperator ? null : { fieldId: draft.fieldId });\n } else if (step === 'operator') setDraft(null);\n else if (!leaveGroup()) setOpen(false);\n setQuery('');\n }, [step, draft, field, fieldOperators, setDraft, leaveGroup]);\n\n // Selection is routed per step and never kept by Base UI (`value` stays null).\n const handleSelect = (item: Item) => {\n if (step === 'field') selectField(item as FilterBarField);\n else if (step === 'operator' && draft) selectOperator(draft.fieldId, item as FilterBarOperator);\n else valueStep.handleSelect(item as FilterBarOption);\n };\n\n // App-level keys run before Base UI's own input handling.\n const handleKeyDown = (event: BaseUIEvent<KeyboardEvent<HTMLInputElement>>) => {\n if (event.key === 'Escape') {\n event.preventDefault();\n // Consumed here: an enclosing popover (advanced filter) must not close on it.\n event.stopPropagation();\n event.preventBaseUIHandler();\n stepBack();\n return;\n }\n if (!open && (event.key === 'ArrowDown' || event.key === 'Enter')) {\n event.preventDefault();\n event.preventBaseUIHandler();\n setOpen(true);\n return;\n }\n if (query === '') {\n if (event.key === 'Backspace') {\n event.preventDefault();\n event.preventBaseUIHandler();\n if (step !== 'field') stepBack();\n else if (targetGroup) {\n // Inside a group: eat its last chip, or drop the group once it is empty.\n const last = targetGroup.nodes.findLast(node => !ctx.leaving.has(node.id));\n if (last) ctx.removeItem(last.id);\n else leaveGroup();\n } else {\n // Chips still animating out are already gone from the value: skip them.\n const last = ctx.items.findLast(item => !ctx.leaving.has(item.id));\n if (last) ctx.removeItem(last.id);\n }\n return;\n }\n if (event.key === 'ArrowLeft' && step === 'field') {\n if (ctx.focusChip(ctx.items.length - 1, -1, 'remove')) event.preventDefault();\n return;\n }\n }\n if (!open) return;\n\n if (event.key === 'Tab' && highlighted && step !== 'value' && (step === 'operator' || query !== '')) {\n event.preventDefault();\n event.preventBaseUIHandler();\n handleSelect(highlighted);\n return;\n }\n if (step === 'value') {\n const highlightedOption = valueStep.hasSuggestions ? (highlighted as FilterBarOption | null) : null;\n const handled = valueStep.handleKeyDown(event, highlightedOption);\n // Base UI closes on Enter when nothing is highlighted (form submission); the draft must stay open.\n if (handled || (event.key === 'Enter' && highlightedOption === null)) event.preventBaseUIHandler();\n }\n };\n\n const optionsForStep: Record<Step, readonly Item[]> = {\n field: visibleFields,\n operator: fieldOperators,\n value: valueStep.options,\n };\n const items: readonly Item[] = emptyForStepChange ? EMPTY_ITEMS : optionsForStep[step];\n\n // A search field is the way out for text that names no field, so it survives the field\n // step's own filtering whatever was typed; every other item matches on its label.\n const filterItem = useCallback(\n (item: Item, text: string, itemToString?: (item: Item) => string) =>\n ('search' in item && item.search === true) || matchesQueryFilter(item, text, itemToString),\n [],\n );\n\n const inputPlaceholder =\n step === 'field'\n ? placeholder\n : step === 'operator'\n ? 'Operator'\n : valueStep.hasSuggestions && valueStep.allowFreeText\n ? 'Search or type a value'\n : field?.type === 'number'\n ? 'Number'\n : 'Value';\n\n return (\n <>\n <ComboboxPrimitive.Root<Item>\n items={items}\n itemToStringLabel={getItemLabel}\n // The value step is already filtered (locally or server-side) by useValueSuggestions.\n filter={step === 'value' ? null : filterItem}\n value={null}\n onValueChange={(item, details) => {\n // Never let Base UI keep the selection, fill the input or close: each step routes it.\n details.cancel();\n if (item) handleSelect(item);\n }}\n inputValue={query}\n onInputValueChange={(next, details) => {\n if (details.reason !== 'input-change') return;\n setQuery(next);\n if (!open) setOpen(true);\n }}\n onItemHighlighted={item => setHighlighted(item ?? null)}\n open={open}\n onOpenChange={(next, details) => {\n // Escape is handled by the input (it steps back rather than closing).\n if (!next && details.reason === 'escape-key') return;\n // The input is the anchor, not a trigger: clicking it must keep the draft open.\n if (\n !next &&\n details.reason === 'outside-press' &&\n details.event.target instanceof Node &&\n inputRef.current?.contains(details.event.target)\n ) {\n return;\n }\n if (next) setOpen(true);\n else close();\n }}\n {...alwaysHighlightProps}\n modal={false}\n >\n <div\n ref={anchorRef}\n data-slot=\"filter-bar-input-trigger\"\n className={cn(\n // Same trigger recipe as every other DS Combobox (fill, radius, `[&>svg]` icon sizing\n // and the Button icon offset); the bar itself has no chrome. Focus lives on the\n // nested input, so the recipe's `focus-visible` border becomes `focus-within`.\n comboboxTriggerClass({ variant: 'default', size: FILTER_BAR_CONTROL_SIZE }),\n 'w-auto cursor-text',\n 'focus-within:bg-fill-hover',\n inputFocusBorderWithin,\n step === 'field' ? 'min-w-40' : 'min-w-28',\n className,\n )}\n >\n <ListFilterIcon aria-hidden className=\"shrink-0\" />\n <ComboboxPrimitive.Input\n ref={el => {\n inputRef.current = el;\n ctx.registerInput(el);\n }}\n aria-label={ariaLabel}\n spellCheck={false}\n {...passwordManagerOptOutProps}\n data-slot=\"filter-bar-input\"\n data-step={step}\n data-target={targetGroup?.id}\n inputMode={step === 'value' && field?.type === 'number' ? 'decimal' : undefined}\n placeholder={inputPlaceholder}\n className={cn(\n unstyledFormElementStyle,\n 'min-w-0 flex-1 bg-transparent',\n 'placeholder:text-muted-foreground placeholder:transition-opacity placeholder:duration-normal focus:placeholder:opacity-70',\n )}\n onFocus={() => setOpen(true)}\n onKeyDown={handleKeyDown}\n />\n </div>\n <ComboboxPrimitive.Portal container={container}>\n <ComboboxPrimitive.Positioner\n // Base UI anchors to the input, which starts after the filter icon; align with the pill instead.\n anchor={anchorRef}\n align=\"start\"\n sideOffset={MENU_SIDE_OFFSET}\n positionMethod={FLOATING_POSITION_METHOD}\n className={comboboxStyles.positioner}\n >\n <ComboboxPrimitive.Popup // Match the pill, with the DS Combobox's 11rem floor (replaces the menu's anchor-width minimum).\n className={cn(comboboxStyles.popup, 'w-(--anchor-width) min-w-44')}\n data-slot=\"filter-bar-editor\"\n >\n {step === 'field' && (\n <FilterBarOptionList<FilterBarField>\n aria-label=\"Fields\"\n getKey={f => f.id}\n renderOption={f => (\n <>\n <FilterBarFieldLabel field={f} />\n {f.search && query !== '' && (\n <span className=\"min-w-0 truncate text-muted-foreground\">\n {ctx.getFieldOperators(f)[0]?.label} \"{query}\"\n </span>\n )}\n </>\n )}\n emptyText=\"No matching field.\"\n />\n )}\n {step === 'operator' && (\n <FilterBarOptionList<FilterBarOperator>\n aria-label=\"Operators\"\n getKey={o => o.id}\n renderOption={o => o.label}\n emptyText=\"No matching operator.\"\n />\n )}\n {step === 'value' && valueStep.hasOptions && (\n <FilterBarOptionList<FilterBarOption>\n aria-label=\"Values\"\n aria-multiselectable={valueStep.isMany || undefined}\n getKey={o => o.value}\n renderOption={option => <FilterBarOptionLabel option={option} />}\n isSelected={o => valueStep.isMany && valueStep.selected.includes(o.value)}\n isLoading={valueStep.isLoading}\n error={valueStep.error}\n emptyText={\n valueStep.allowFreeText ? 'No suggestions — press Enter to use your text.' : 'No matching value.'\n }\n />\n )}\n {step === 'value' && !valueStep.hasSuggestions && (\n <div className=\"flex items-center justify-between gap-2 py-1 pr-1 pl-[.9em]\">\n <Txt variant=\"caption\" tone=\"muted\">\n Type a value\n </Txt>\n <Button\n size=\"sm\"\n variant=\"default\"\n disabled={!valueStep.canCommitQuery}\n onMouseDown={e => e.preventDefault()}\n onClick={() => valueStep.submitFreeText()}\n >\n Apply\n <Kbd size=\"xs\">↵</Kbd>\n </Button>\n </div>\n )}\n {step === 'value' && valueStep.isMany && (\n <div className=\"flex items-center justify-end gap-1 border-t border-border p-1\">\n <Button\n size=\"sm\"\n variant=\"default\"\n onMouseDown={e => e.preventDefault()}\n onClick={() => valueStep.commitDone()}\n >\n Done\n <Kbd size=\"xs\">{modEnterLabel}</Kbd>\n </Button>\n </div>\n )}\n </ComboboxPrimitive.Popup>\n </ComboboxPrimitive.Positioner>\n </ComboboxPrimitive.Portal>\n </ComboboxPrimitive.Root>\n </>\n );\n}\n","import { useEffect } from 'react';\nimport { useFilterBarContext } from './filter-bar-context';\n\n/** Keeps a leaving node in the DOM until its exit animation has played, then releases it. */\nexport function useSettleOnLeave(id: string, leaving: boolean, rootRef: React.RefObject<HTMLElement | null>) {\n const { settleRemove } = useFilterBarContext();\n useEffect(() => {\n const root = rootRef.current;\n if (!leaving || !root) return;\n const animations = typeof root.getAnimations === 'function' ? root.getAnimations({ subtree: true }) : [];\n if (animations.length === 0) {\n settleRemove(id);\n return;\n }\n let cancelled = false;\n Promise.all(animations.map(animation => animation.finished))\n .then(() => {\n if (!cancelled) settleRemove(id);\n })\n .catch(() => {});\n return () => {\n cancelled = true;\n };\n }, [leaving, id, settleRemove, rootRef]);\n}\n","import { FolderIcon, FolderPlusIcon, PlusIcon, Trash2Icon } from 'lucide-react';\nimport { Fragment, useEffect, useRef } from 'react';\nimport type { ReactNode } from 'react';\nimport { FilterBarChip } from './filter-bar-chip';\nimport { useFilterBarContext } from './filter-bar-context';\nimport { FilterBarInput } from './filter-bar-input';\nimport { countLeaves } from './filter-bar-tree';\nimport type { FilterBarGroup, FilterBarLogic } from './types';\nimport { isFilterBarGroup } from './types';\nimport { useSettleOnLeave } from './use-settle-on-leave';\nimport { Button } from '@/ds/components/Button/Button';\nimport { Txt } from '@/ds/components/Txt';\nimport { cn } from '@/lib/utils';\n\nconst connectorClass =\n 'flex h-control-sm w-14 shrink-0 items-center justify-center rounded-md text-column tracking-wide text-muted-foreground uppercase';\n\nexport type FilterBarLogicToggleProps = {\n groupId: string;\n logic: FilterBarLogic;\n className?: string;\n};\n\n/** `and` / `or` connector in front of a row; every connector of a group shares its logic. */\nexport function FilterBarLogicToggle({ groupId, logic, className }: FilterBarLogicToggleProps) {\n const ctx = useFilterBarContext();\n const next: FilterBarLogic = logic === 'and' ? 'or' : 'and';\n return (\n <button\n type=\"button\"\n data-slot=\"filter-bar-logic\"\n data-logic={logic}\n aria-label={`Joined with ${logic}, switch to ${next}`}\n title={`Switch to ${next}`}\n className={cn(\n connectorClass,\n 'filter-bar-logic cursor-pointer border border-border bg-fill-subtle outline-none',\n 'hover:bg-fill-hover hover:text-foreground focus-visible:bg-fill-hover focus-visible:text-foreground',\n className,\n )}\n onClick={() => ctx.setLogic(groupId, next)}\n >\n {logic}\n </button>\n );\n}\n\n/** Segmented `and | or` control shown in a nested group's header. */\nfunction FilterBarLogicSwitch({ groupId, logic }: { groupId: string; logic: FilterBarLogic }) {\n const ctx = useFilterBarContext();\n return (\n <div\n role=\"radiogroup\"\n aria-label=\"Group logic\"\n className=\"flex h-control-sm items-center gap-0.5 rounded-md border border-border bg-fill-subtle p-0.5\"\n >\n {(['and', 'or'] as const).map(value => (\n <button\n key={value}\n type=\"button\"\n role=\"radio\"\n aria-checked={logic === value}\n aria-label={`Join with ${value}`}\n className={cn(\n 'h-full cursor-pointer rounded-sm px-1.5 text-column tracking-wide uppercase outline-none',\n 'focus-visible:bg-fill-hover',\n logic === value ? 'bg-fill-hover text-foreground' : 'text-muted-foreground hover:text-foreground',\n )}\n onClick={() => logic !== value && ctx.setLogic(groupId, value)}\n >\n {value}\n </button>\n ))}\n </div>\n );\n}\n\nexport type FilterBarGroupEditorProps = {\n group: FilterBarGroup;\n /** Nesting level of `group` (root-level group = 1). */\n depth: number;\n /** Drops this group; rendered as a trailing `Clear all` in the footer. */\n onRemove?: () => void;\n removeLabel?: string;\n className?: string;\n};\n\n/**\n * Recursive rule builder shown in an advanced-filter popover. Rows are laid out as\n * `connector | condition`: the first row reads `where`, the following ones carry the\n * group's `and` / `or` toggle. Nested groups render as bordered cards with their own\n * header (logic switch + remove) and footer. The shared typeahead input renders as the\n * last row of the group it is pointed at.\n */\nexport function FilterBarGroupEditor({\n group,\n depth,\n onRemove,\n removeLabel = 'Remove group',\n className,\n}: FilterBarGroupEditorProps) {\n const ctx = useFilterBarContext();\n const addFilterRef = useRef<HTMLButtonElement>(null);\n const focusAddFilter = useRef(false);\n const targeted = ctx.inputTarget === group.id;\n const canNest = depth < ctx.maxDepth;\n\n // `+ Condition` is hidden while the input is open; focus it once it remounts.\n useEffect(() => {\n if (targeted || !focusAddFilter.current) return;\n focusAddFilter.current = false;\n addFilterRef.current?.focus();\n }, [targeted]);\n\n const rows: ReactNode[] = [];\n const connector = (key: string) =>\n rows.length === 0 ? (\n <span key={`${key}:where`} className={connectorClass}>\n where\n </span>\n ) : (\n <FilterBarLogicToggle key={`${key}:logic`} groupId={group.id} logic={group.logic} />\n );\n for (const node of group.nodes) {\n rows.push(\n <Fragment key={node.id}>\n {connector(node.id)}\n {isFilterBarGroup(node) ? (\n <NestedGroupCard group={node} depth={depth + 1} />\n ) : (\n <FilterBarChip item={node} className=\"w-fit\" />\n )}\n </Fragment>,\n );\n }\n if (ctx.draft && ctx.draft.groupId === group.id) {\n const { id, fieldId, operatorId = '' } = ctx.draft;\n rows.push(\n <Fragment key={id}>\n {connector(id)}\n <FilterBarChip draft item={{ id, fieldId, operatorId, value: '' }} className=\"w-fit\" />\n </Fragment>,\n );\n }\n if (targeted) {\n rows.push(\n <Fragment key=\"input\">\n {connector('input')}\n <FilterBarInput\n groupId={group.id}\n placeholder=\"Add condition\"\n onLeave={() => {\n focusAddFilter.current = true;\n }}\n />\n </Fragment>,\n );\n }\n\n return (\n <div\n data-slot=\"filter-bar-group-editor\"\n data-depth={depth}\n role=\"group\"\n aria-label={`Conditions joined with ${group.logic}`}\n className={cn('flex min-w-0 flex-col', className)}\n >\n {rows.length > 0 && (\n <div className=\"grid grid-cols-[auto_minmax(0,1fr)] items-start gap-x-2 gap-y-1.5 p-2\">{rows}</div>\n )}\n <div\n data-slot=\"filter-bar-editor-actions\"\n className={cn('flex w-full items-center gap-1 p-1', rows.length > 0 && 'border-t border-border')}\n >\n {!targeted && (\n <Button\n ref={addFilterRef}\n variant=\"ghost\"\n size=\"sm\"\n icon={<PlusIcon />}\n onClick={() => ctx.openGroupInput(group.id)}\n >\n Condition\n </Button>\n )}\n <Button\n variant=\"ghost\"\n size=\"sm\"\n icon={<FolderPlusIcon />}\n className=\"text-muted-foreground\"\n tooltip={canNest ? undefined : `Groups can nest ${ctx.maxDepth} levels deep`}\n disabled={!canNest}\n onClick={() => ctx.addGroup(group.id, group.logic === 'and' ? 'or' : 'and')}\n >\n Group\n </Button>\n {onRemove && (\n <Button\n variant=\"ghost\"\n size=\"sm\"\n icon={<Trash2Icon />}\n className=\"ml-auto text-muted-foreground\"\n aria-label={removeLabel}\n onClick={onRemove}\n >\n Clear all\n </Button>\n )}\n </div>\n </div>\n );\n}\n\nfunction NestedGroupCard({ group, depth }: { group: FilterBarGroup; depth: number }) {\n const ctx = useFilterBarContext();\n const rootRef = useRef<HTMLDivElement>(null);\n const leaving = ctx.leaving.has(group.id);\n useSettleOnLeave(group.id, leaving, rootRef);\n const count = countLeaves(group);\n\n return (\n <div\n ref={rootRef}\n data-slot=\"filter-bar-editor-nested\"\n data-leaving={leaving || undefined}\n aria-hidden={leaving || undefined}\n className={cn(\n 'filter-bar-editor-nested w-full overflow-hidden rounded-lg border border-border',\n leaving && 'pointer-events-none',\n )}\n >\n <div className=\"flex items-center gap-2 border-b border-border px-2 py-1\">\n <FolderIcon className=\"size-3.5 text-muted-foreground\" />\n <Txt as=\"span\" variant=\"label\" tone=\"ink\">\n Group\n </Txt>\n <Txt as=\"span\" variant=\"label\" tone=\"muted\">\n · {count} {count === 1 ? 'condition' : 'conditions'}\n </Txt>\n <div className=\"ml-auto flex items-center gap-1\">\n <FilterBarLogicSwitch groupId={group.id} logic={group.logic} />\n <Button\n variant=\"ghost\"\n size=\"icon-sm\"\n tooltip=\"Remove group\"\n disabled={leaving}\n onClick={() => ctx.removeGroup(group.id)}\n >\n <Trash2Icon />\n </Button>\n </div>\n </div>\n <FilterBarGroupEditor group={group} depth={depth} />\n </div>\n );\n}\n","import { BracesIcon, XIcon } from 'lucide-react';\nimport { useRef, useState } from 'react';\nimport type { KeyboardEvent } from 'react';\nimport { chipClass, editableSegmentClass, removeSegmentClass } from './filter-bar-chip';\nimport { FILTER_BAR_SCOPE_ATTR, useFilterBarContext } from './filter-bar-context';\nimport { FilterBarGroupEditor } from './filter-bar-group-editor';\nimport { countLeaves } from './filter-bar-tree';\nimport type { FilterBarGroup } from './types';\nimport { useSettleOnLeave } from './use-settle-on-leave';\nimport { Button } from '@/ds/components/Button/Button';\nimport { Popover, PopoverContent, PopoverTrigger } from '@/ds/components/Popover';\nimport { Txt } from '@/ds/components/Txt';\nimport { cn } from '@/lib/utils';\n\nexport type FilterBarAdvancedChipProps = {\n group: FilterBarGroup;\n className?: string;\n};\n\n/**\n * A root-level group rendered as one \"Advanced filter\" chip. Its popover hosts the\n * recursive rule builder; the chip's remove button drops the whole subtree.\n */\nexport function FilterBarAdvancedChip({ group, className }: FilterBarAdvancedChipProps) {\n const ctx = useFilterBarContext();\n const [initial] = useState(() => !ctx.mounted);\n const rootRef = useRef<HTMLDivElement>(null);\n const triggerRef = useRef<HTMLButtonElement>(null);\n const leaving = ctx.leaving.has(group.id);\n const open = ctx.openGroupId === group.id;\n const count = countLeaves(group);\n // Position in the flattened item list: navigation from the chip continues from its first leaf.\n const firstLeafIndex = ctx.items.findIndex(item => isUnder(group, item.id));\n const index = firstLeafIndex === -1 ? ctx.items.length : firstLeafIndex;\n useSettleOnLeave(group.id, leaving, rootRef);\n\n const handleKeyDown = (event: KeyboardEvent<HTMLDivElement>) => {\n if (leaving) return;\n const segments = Array.from(rootRef.current?.querySelectorAll<HTMLElement>('[data-filter-bar-segment]') ?? []);\n const current = segments.findIndex(el => el === event.target);\n if (current === -1) return;\n switch (event.key) {\n case 'ArrowRight': {\n event.preventDefault();\n const next = segments[current + 1];\n if (next) next.focus();\n else if (!ctx.focusChip(index + count, 1, 'field')) ctx.focusInput();\n return;\n }\n case 'ArrowLeft': {\n event.preventDefault();\n const prev = segments[current - 1];\n if (prev) prev.focus();\n else ctx.focusChip(index - 1, -1, 'remove');\n return;\n }\n case 'Delete':\n case 'Backspace':\n event.preventDefault();\n remove();\n break;\n default:\n }\n };\n\n const remove = () => {\n ctx.removeGroup(group.id);\n ctx.focusAfterRemove(index);\n };\n\n return (\n <Popover open={open} onOpenChange={next => ctx.setOpenGroup(next ? group.id : null)}>\n <div\n ref={rootRef}\n role=\"group\"\n aria-label={`Advanced filter, ${count} ${count === 1 ? 'condition' : 'conditions'}`}\n aria-hidden={leaving || undefined}\n data-slot=\"filter-bar-advanced\"\n data-initial={initial || undefined}\n data-leaving={leaving || undefined}\n className={cn('filter-bar-advanced', chipClass, leaving && 'pointer-events-none', className)}\n onKeyDown={handleKeyDown}\n >\n <PopoverTrigger\n ref={el => {\n triggerRef.current = el;\n ctx.registerSegment(group.id, 'field', leaving ? null : el);\n }}\n render={<button type=\"button\" />}\n data-filter-bar-segment=\"field\"\n className={editableSegmentClass}\n title=\"Edit advanced filter\"\n >\n <BracesIcon aria-hidden />\n <span className=\"truncate\">Advanced filter</span>\n {count > 0 && (\n <Txt as=\"span\" variant=\"column\" tone=\"muted\" aria-hidden>\n {count}\n </Txt>\n )}\n </PopoverTrigger>\n {leaving ? (\n <span aria-hidden className={removeSegmentClass}>\n <XIcon />\n </span>\n ) : (\n <button\n type=\"button\"\n ref={el => ctx.registerSegment(group.id, 'remove', el)}\n data-filter-bar-segment=\"remove\"\n aria-label=\"Remove advanced filter\"\n title=\"Remove advanced filter\"\n className={removeSegmentClass}\n onClick={remove}\n >\n <XIcon />\n </button>\n )}\n </div>\n <PopoverContent\n align=\"start\"\n className=\"w-[min(92vw,44rem)] p-0\"\n {...{ [FILTER_BAR_SCOPE_ATTR]: 'advanced' }}\n finalFocus={triggerRef}\n >\n <div className=\"flex items-center gap-2 border-b border-border px-3 py-2\">\n <BracesIcon className=\"size-3.5 text-muted-foreground\" />\n <Txt as=\"span\" variant=\"label\" tone=\"ink\">\n Advanced filter\n </Txt>\n <Txt as=\"span\" variant=\"column\" tone=\"muted\" className=\"rounded-md bg-fill-subtle px-1.5\">\n {count}\n </Txt>\n <Button\n variant=\"ghost\"\n size=\"icon-sm\"\n className=\"ml-auto\"\n tooltip=\"Close\"\n onClick={() => ctx.setOpenGroup(null)}\n >\n <XIcon />\n </Button>\n </div>\n <FilterBarGroupEditor\n group={group}\n depth={1}\n removeLabel=\"Remove advanced filter\"\n onRemove={() => {\n ctx.setOpenGroup(null);\n remove();\n }}\n />\n </PopoverContent>\n </Popover>\n );\n}\n\nconst isUnder = (group: FilterBarGroup, itemId: string): boolean =>\n group.nodes.some(node => (node.id === itemId ? true : 'kind' in node && isUnder(node, itemId)));\n","import { useFilterBarContext } from './filter-bar-context';\nimport { ClearFiltersButton } from '@/ds/components/ClearFiltersButton/clear-filters-button';\n\n/** Removes every removable filter. Rendered by FilterBar at its trailing edge; hidden while nothing can be removed. */\nexport function FilterBarClear({ label }: { label: string }) {\n const ctx = useFilterBarContext();\n if (!ctx.hasRemovableItems) return null;\n return (\n <ClearFiltersButton\n label={label}\n onClick={event => {\n event.stopPropagation();\n ctx.clear();\n ctx.focusInput();\n }}\n />\n );\n}\n","import { Fragment } from 'react';\nimport type { ReactNode } from 'react';\nimport { FilterBarAdvancedChip } from './filter-bar-advanced-chip';\nimport { FilterBarChip } from './filter-bar-chip';\nimport { FilterBarClear } from './filter-bar-clear';\nimport { FILTER_BAR_SCOPE_ATTR, FilterBarProvider, useFilterBarContext } from './filter-bar-context';\nimport { FilterBarInput } from './filter-bar-input';\nimport { FilterBarTimeRange } from './filter-bar-time-range';\nimport { isFilterBarGroup } from './types';\nimport type { FilterBarExpression, FilterBarField, FilterBarItem, FilterBarOperator } from './types';\nimport { VisuallyHidden } from '@/ds/primitives/visually-hidden';\nimport { cn } from '@/lib/utils';\n\ntype FilterBarValueProps =\n | {\n /** Flat list of filters, implicitly joined with `and`. Advanced filters are never offered. */\n value: FilterBarItem[];\n onValueChange: (items: FilterBarItem[]) => void;\n }\n | {\n /**\n * Tree of filters and groups. Root nodes are joined with `and`; each root group renders\n * as one \"Advanced filter\" chip whose popover edits the nested `and` / `or` logic.\n */\n value: FilterBarExpression;\n onValueChange: (expression: FilterBarExpression) => void;\n };\n\nexport type FilterBarProps = FilterBarValueProps & {\n fields: FilterBarField[];\n operators: FilterBarOperator[];\n /**\n * Id given to a newly added item. Defaults to a random id. Consumers that rebuild `value` from\n * their own store (URL, query params…) should return the id they will rebuild it with, so the\n * draft chip and the committed chip are the same element.\n */\n createItemId?: (fieldId: string) => string;\n /** How deep advanced-filter groups may nest (root-level group = 1). Defaults to 3. */\n maxDepth?: number;\n 'aria-label'?: string;\n /**\n * Text shown in a value list when the field's `suggestions` resolver rejects, for example\n * to explain a server limit. Return `undefined` to keep the default \"Couldn't load values.\".\n */\n describeSuggestionsError?: (error: unknown) => string | undefined;\n /** Accessible label of the trailing \"remove every filter\" button. */\n clearLabel?: string;\n className?: string;\n children: ReactNode;\n};\n\nfunction FilterBarSurface({\n className,\n clearLabel,\n children,\n}: {\n className?: string;\n clearLabel: string;\n children: ReactNode;\n}) {\n const ctx = useFilterBarContext();\n return (\n <div\n role=\"group\"\n aria-label={ctx.ariaLabel}\n data-slot=\"filter-bar\"\n {...{ [FILTER_BAR_SCOPE_ATTR]: 'bar' }}\n className={cn(\n // No chrome of its own: chips and the typeahead input sit directly on the parent surface.\n // Layout: chips, input, then Clear right beside the input — all in one wrapping row so\n // Clear never drifts to the far edge of a wide container.\n 'flex w-full flex-wrap items-center gap-1.5',\n className,\n )}\n >\n {children}\n <span className=\"flex shrink-0 items-center empty:hidden\">\n <FilterBarClear label={clearLabel} />\n </span>\n <VisuallyHidden aria-live=\"polite\">{ctx.announcement}</VisuallyHidden>\n </div>\n );\n}\n\n/**\n * Braintrust-style filter bar: `field → operator → value` filters built from a\n * single typeahead input, rendered as inline editable chips. Domain-agnostic —\n * fields, operators and values are plain strings supplied by the consumer.\n *\n * Pass a `FilterBarExpression` as `value` to enable Linear-style advanced filters:\n * the input offers \"Advanced filter…\", which adds one chip whose popover hosts a\n * recursive rule builder (`and` / `or` connectors, nested groups). The bar itself\n * stays flat. A flat `FilterBarItem[]` stays flat.\n *\n * @example\n * <FilterBar value={items} onValueChange={setItems} fields={fields} operators={DEFAULT_FILTER_OPERATORS}>\n * <FilterBar.Chips />\n * <FilterBar.Input />\n * </FilterBar>\n */\nexport function FilterBar({\n fields,\n operators,\n value,\n onValueChange,\n createItemId,\n maxDepth,\n 'aria-label': ariaLabel = 'Filters',\n describeSuggestionsError,\n clearLabel = 'Clear filters',\n className,\n children,\n}: FilterBarProps) {\n return (\n <FilterBarProvider\n fields={fields}\n operators={operators}\n value={value}\n onValueChange={onValueChange}\n createItemId={createItemId}\n maxDepth={maxDepth}\n ariaLabel={ariaLabel}\n describeSuggestionsError={describeSuggestionsError}\n >\n <FilterBarSurface className={className} clearLabel={clearLabel}>\n {children}\n </FilterBarSurface>\n </FilterBarProvider>\n );\n}\n\n/**\n * Default layout: one editable chip per root item, one \"Advanced filter\" chip per root\n * group, in order, then the chip of the filter being built in the bar's input (which\n * becomes the last item's chip once committed).\n */\nexport function FilterBarChips({ renderChip = defaultRenderChip }: FilterBarChipsProps) {\n const ctx = useFilterBarContext();\n // One keyed array: the draft chip and the item it becomes share a key, so React\n // keeps the element across the commit instead of mounting a new chip.\n const chips: ReactNode[] = [];\n for (const node of ctx.expression.nodes) {\n const chip = isFilterBarGroup(node) ? <FilterBarAdvancedChip group={node} /> : renderChip(node);\n if (chip !== null) chips.push(<Fragment key={node.id}>{chip}</Fragment>);\n }\n if (ctx.draft && !ctx.draft.groupId) {\n // `FilterBarChip` needs a full item; the draft's missing parts are blank until picked.\n const { id, fieldId, operatorId = '' } = ctx.draft;\n chips.push(\n <Fragment key={id}>\n <FilterBarChip draft item={{ id, fieldId, operatorId, value: '' }} />\n </Fragment>,\n );\n }\n return <>{chips}</>;\n}\n\nexport type FilterBarChipsProps = {\n /**\n * Chip for an item; return `null` to render none (e.g. an item only held in the\n * value for scoping). Defaults to a plain editable `FilterBar.Chip`.\n */\n renderChip?: (item: FilterBarItem) => ReactNode;\n};\n\nconst defaultRenderChip = (item: FilterBarItem) => <FilterBarChip item={item} />;\n\nFilterBar.Chips = FilterBarChips;\nFilterBar.Chip = FilterBarChip;\nFilterBar.AdvancedChip = FilterBarAdvancedChip;\nFilterBar.Input = FilterBarInput;\nFilterBar.TimeRange = FilterBarTimeRange;\n","import type { FilterBarOperator } from './types';\n\n/** Opt-in starter set. Pure data: the component attaches no semantics to ids. */\nexport const DEFAULT_FILTER_OPERATORS: FilterBarOperator[] = [\n { id: 'is', label: 'is', widensTo: 'in' },\n { id: 'is-not', label: 'is not' },\n { id: 'contains', label: 'contains' },\n { id: 'not-contains', label: 'does not contain' },\n { id: 'starts-with', label: 'starts with' },\n { id: 'gt', label: '>' },\n { id: 'lt', label: '<' },\n { id: 'gte', label: '>=' },\n { id: 'lte', label: '<=' },\n { id: 'is-empty', label: 'is empty', arity: 'none' },\n { id: 'is-not-empty', label: 'is not empty', arity: 'none' },\n { id: 'in', label: 'in', arity: 'many' },\n];\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AA8BA,IAAM,gBAAgB,SAAgB,WAAW,QAAQ,KAAK,QAAQ,KAAK,QAAQ,WAAW,OAAO,KAAK,QAAQ;AAElH,IAAM,cAA+B,CAAC;;AAEtC,IAAM,oBAAoB;AAC1B,IAAM,iBAAiC;CACrC,IAAI;CACJ,OAAO;CACP,MAAM;CACN,WAAW,CAAC;AACd;;;;;AAmBA,SAAgB,eAAe,OAA4B;CAEzD,IADY,oBACR,CAAA,CAAI,gBAAgB,MAAM,SAAS,OAAO;CAC9C,OAAO,oBAAC,oBAAD,EAAoB,GAAI,MAAQ,CAAA;AACzC;AAEA,SAAS,mBAAmB,EAC1B,cAAc,UACd,WACA,cAAc,YAAY,cAC1B,SACA,WACsB;CACtB,MAAM,MAAM,oBAAoB;CAChC,MAAM,YAAY,mBAAmB;CACrC,MAAM,WAAW,OAAgC,IAAI;CACrD,MAAM,YAAY,OAAuB,IAAI;CAC7C,MAAM,CAAC,MAAM,WAAW,SAAS,KAAK;CACtC,MAAM,CAAC,OAAO,YAAY,SAAS,EAAE;CACrC,MAAM,CAAC,aAAa,kBAAkB,SAAsB,IAAI;CAChE,MAAM,CAAC,oBAAoB,yBAAyB,SAAS,KAAK;CAClE,MAAM,gBAAgB,mBAAmB,IAAI,OAAO;CAGpD,MAAM,EAAE,OAAO,UAAU,eAAe,gBAAgB;CACxD,MAAM,OAAa,CAAC,QAAQ,UAAU,CAAC,MAAM,aAAa,aAAa;CACvE,MAAM,QAAQ,QAAQ,IAAI,SAAS,MAAM,OAAO,IAAI,KAAA;CACpD,MAAM,iBAAiB,cAAe,QAAQ,IAAI,kBAAkB,KAAK,IAAI,CAAC,GAAI,CAAC,KAAK,KAAK,CAAC;CAC9F,MAAM,WAAW,OAAO,aACnB,eAAe,MAAK,MAAK,EAAE,OAAO,MAAM,UAAU,KAAK,IAAI,YAAY,MAAM,UAAU,IACxF,KAAA;CAEJ,MAAM,gBAAgB,IAAI,iBAAiB,YAAY,KAAA;CACvD,MAAM,gBAAgB,cAAc;EAClC,MAAM,SAAS,IAAI,OAAO,QAAO,MAAK,CAAC,EAAE,MAAM;EAC/C,OAAO,gBAAgB,CAAC,GAAG,QAAQ,cAAc,IAAI;CACvD,GAAG,CAAC,IAAI,QAAQ,aAAa,CAAC;CAC9B,MAAM,cAAc,UAAU,UAAU,IAAI,YAAY,OAAO,IAAI,KAAA;CAGnE,gBAAgB;EACd,IAAI,SAAS,SAAS,SAAS,MAAM;CACvC,GAAG,CAAC,OAAO,CAAC;CAKZ,MAAM,qBAAqB,aAAa,WAAuB;EAC7D,gBAAgB,sBAAsB,IAAI,CAAC;EAC3C,OAAO;EACP,sBAAsB,KAAK;CAC7B,GAAG,CAAC,CAAC;CAEL,MAAM,WAAW,aACd,SAAqD,yBAAyB,cAAc,IAAI,CAAC,GAClG,CAAC,oBAAoB,aAAa,CACpC;CAEA,MAAM,QAAQ,kBAAkB;EAC9B,cAAc,IAAI;EAClB,SAAS,EAAE;CACb,GAAG,CAAC,aAAa,CAAC;CAElB,MAAM,QAAQ,kBAAkB;EAC9B,QAAQ,KAAK;EACb,MAAM;CACR,GAAG,CAAC,KAAK,CAAC;CAEV,MAAM,SAAS,aACZ,SAAiB,YAAoB,UAA0B;EAC9D,yBAAyB,YAAY;GAAE;GAAS;EAAW,GAAG,KAAK,CAAC;EACpE,SAAS,EAAE;EACX,SAAS,SAAS,MAAM;CAC1B,GACA,CAAC,oBAAoB,WAAW,CAClC;CAEA,MAAM,iBAAiB,aACpB,SAAiB,SAA4B;EAC5C,IAAI,KAAK,UAAU,QAAQ;GACzB,OAAO,SAAS,KAAK,IAAI,EAAE;GAC3B;EACF;EACA,SAAS;GAAE;GAAS,YAAY,KAAK;EAAG,CAAC;EACzC,SAAS,EAAE;CACb,GACA,CAAC,QAAQ,QAAQ,CACnB;CAEA,MAAM,cAAc,aACjB,SAAyB;EACxB,IAAI,KAAK,OAAO,mBAAmB;GAEjC,MAAM,KAAK,IAAI,SAAS,KAAA,GAAW,IAAI;GACvC,IAAI,aAAa,EAAE;GACnB,IAAI,eAAe,EAAE;GACrB,SAAS,EAAE;GACX,QAAQ,KAAK;GACb;EACF;EACA,MAAM,CAAC,MAAM,GAAG,QAAQ,IAAI,kBAAkB,IAAI;EAGlD,IAAI,KAAK,UAAU,QAAQ,MAAM,KAAK,MAAM,IAAI;GAC9C,OAAO,KAAK,IAAI,KAAK,IAAI,gBAAgB,KAAK,MAAM,KAAK,CAAC;GAC1D;EACF;EAEA,IAAI,QAAQ,KAAK,WAAW,GAAG;GAC7B,eAAe,KAAK,IAAI,IAAI;GAC5B;EACF;EACA,SAAS,EAAE,SAAS,KAAK,GAAG,CAAC;EAC7B,SAAS,EAAE;CACb,GACA;EAAC;EAAK;EAAQ;EAAO;EAAgB;CAAQ,CAC/C;CAEA,MAAM,YAAY,aAAa;EAC7B;EACA;EACA;EACA,SAAS,QAAQ,SAAS;EAC1B;EACA,WAAU,UAAS;GACjB,IAAI,OAAO,YAAY,OAAO,MAAM,SAAS,MAAM,YAAY,KAAK;EACtE;CACF,CAAC;CAID,MAAM,aAAa,kBAAkB;EACnC,IAAI,CAAC,SAAS,OAAO;EACrB,IAAI,eAAe,KAAA,CAAS;EAC5B,UAAU;EACV,OAAO;CACT,GAAG;EAAC;EAAK;EAAS;CAAO,CAAC;CAE1B,MAAM,WAAW,kBAAkB;EACjC,IAAI,SAAS,WAAW,OAAO;GAE7B,MAAM,eAAe,QAAQ,eAAe,WAAW,IAAI;GAC3D,SAAS,eAAe,OAAO,EAAE,SAAS,MAAM,QAAQ,CAAC;EAC3D,OAAO,IAAI,SAAS,YAAY,SAAS,IAAI;OACxC,IAAI,CAAC,WAAW,GAAG,QAAQ,KAAK;EACrC,SAAS,EAAE;CACb,GAAG;EAAC;EAAM;EAAO;EAAO;EAAgB;EAAU;CAAU,CAAC;CAG7D,MAAM,gBAAgB,SAAe;EACnC,IAAI,SAAS,SAAS,YAAY,IAAsB;OACnD,IAAI,SAAS,cAAc,OAAO,eAAe,MAAM,SAAS,IAAyB;OACzF,UAAU,aAAa,IAAuB;CACrD;CAGA,MAAM,iBAAiB,UAAwD;EAC7E,IAAI,MAAM,QAAQ,UAAU;GAC1B,MAAM,eAAe;GAErB,MAAM,gBAAgB;GACtB,MAAM,qBAAqB;GAC3B,SAAS;GACT;EACF;EACA,IAAI,CAAC,SAAS,MAAM,QAAQ,eAAe,MAAM,QAAQ,UAAU;GACjE,MAAM,eAAe;GACrB,MAAM,qBAAqB;GAC3B,QAAQ,IAAI;GACZ;EACF;EACA,IAAI,UAAU,IAAI;GAChB,IAAI,MAAM,QAAQ,aAAa;IAC7B,MAAM,eAAe;IACrB,MAAM,qBAAqB;IAC3B,IAAI,SAAS,SAAS,SAAS;SAC1B,IAAI,aAAa;KAEpB,MAAM,OAAO,YAAY,MAAM,UAAS,SAAQ,CAAC,IAAI,QAAQ,IAAI,KAAK,EAAE,CAAC;KACzE,IAAI,MAAM,IAAI,WAAW,KAAK,EAAE;UAC3B,WAAW;IAClB,OAAO;KAEL,MAAM,OAAO,IAAI,MAAM,UAAS,SAAQ,CAAC,IAAI,QAAQ,IAAI,KAAK,EAAE,CAAC;KACjE,IAAI,MAAM,IAAI,WAAW,KAAK,EAAE;IAClC;IACA;GACF;GACA,IAAI,MAAM,QAAQ,eAAe,SAAS,SAAS;IACjD,IAAI,IAAI,UAAU,IAAI,MAAM,SAAS,GAAG,IAAI,QAAQ,GAAG,MAAM,eAAe;IAC5E;GACF;EACF;EACA,IAAI,CAAC,MAAM;EAEX,IAAI,MAAM,QAAQ,SAAS,eAAe,SAAS,YAAY,SAAS,cAAc,UAAU,KAAK;GACnG,MAAM,eAAe;GACrB,MAAM,qBAAqB;GAC3B,aAAa,WAAW;GACxB;EACF;EACA,IAAI,SAAS,SAAS;GACpB,MAAM,oBAAoB,UAAU,iBAAkB,cAAyC;GAG/F,IAFgB,UAAU,cAAc,OAAO,iBAE3C,KAAY,MAAM,QAAQ,WAAW,sBAAsB,MAAO,MAAM,qBAAqB;EACnG;CACF;CAEA,MAAM,iBAAgD;EACpD,OAAO;EACP,UAAU;EACV,OAAO,UAAU;CACnB;CACA,MAAM,QAAyB,qBAAqB,cAAc,eAAe;CAIjF,MAAM,aAAa,aAChB,MAAY,MAAc,iBACxB,YAAY,QAAQ,KAAK,WAAW,QAAS,mBAAmB,MAAM,MAAM,YAAY,GAC3F,CAAC,CACH;CAEA,MAAM,mBACJ,SAAS,UACL,cACA,SAAS,aACP,aACA,UAAU,kBAAkB,UAAU,gBACpC,2BACA,OAAO,SAAS,WACd,WACA;CAEZ,OACE,oBAAAA,YAAA,EAAA,UACE,qBAAC,kBAAkB,MAAnB;EACS;EACP,mBAAmB;EAEnB,QAAQ,SAAS,UAAU,OAAO;EAClC,OAAO;EACP,gBAAgB,MAAM,YAAY;GAEhC,QAAQ,OAAO;GACf,IAAI,MAAM,aAAa,IAAI;EAC7B;EACA,YAAY;EACZ,qBAAqB,MAAM,YAAY;GACrC,IAAI,QAAQ,WAAW,gBAAgB;GACvC,SAAS,IAAI;GACb,IAAI,CAAC,MAAM,QAAQ,IAAI;EACzB;EACA,oBAAmB,SAAQ,eAAe,QAAQ,IAAI;EAChD;EACN,eAAe,MAAM,YAAY;GAE/B,IAAI,CAAC,QAAQ,QAAQ,WAAW,cAAc;GAE9C,IACE,CAAC,QACD,QAAQ,WAAW,mBACnB,QAAQ,MAAM,kBAAkB,QAChC,SAAS,SAAS,SAAS,QAAQ,MAAM,MAAM,GAE/C;GAEF,IAAI,MAAM,QAAQ,IAAI;QACjB,MAAM;EACb;EACA,GAAI;EACJ,OAAO;EAnCT,UAAA,CAqCE,qBAAC,OAAD;GACE,KAAK;GACL,aAAU;GACV,WAAW,GAIT,qBAAqB;IAAE,SAAS;IAAW,MAAA;GAA8B,CAAC,GAC1E,sBACA,8BACA,wBACA,SAAS,UAAU,aAAa,YAChC,SACF;GAbF,UAAA,CAeE,oBAAC,gBAAD;IAAgB,eAAA;IAAY,WAAU;GAAY,CAAA,GAClD,oBAAC,kBAAkB,OAAnB;IACE,MAAK,OAAM;KACT,SAAS,UAAU;KACnB,IAAI,cAAc,EAAE;IACtB;IACA,cAAY;IACZ,YAAY;IACZ,GAAI;IACJ,aAAU;IACV,aAAW;IACX,eAAa,aAAa;IAC1B,WAAW,SAAS,WAAW,OAAO,SAAS,WAAW,YAAY,KAAA;IACtE,aAAa;IACb,WAAW,GACT,0BACA,iCACA,2HACF;IACA,eAAe,QAAQ,IAAI;IAC3B,WAAW;GACZ,CAAA,CACE;EACL,CAAA,GAAA,oBAAC,kBAAkB,QAAnB;GAAqC;GACnC,UAAA,oBAAC,kBAAkB,YAAnB;IAEE,QAAQ;IACR,OAAM;IACN,YAAA;IACA,gBAAgB;IAChB,WAAW,eAAe;IAE1B,UAAA,qBAAC,kBAAkB,OAAnB;KACE,WAAW,GAAG,eAAe,OAAO,6BAA6B;KACjE,aAAU;KAFZ,UAAA;MAIG,SAAS,WACR,oBAAC,qBAAD;OACE,cAAW;OACX,SAAQ,MAAK,EAAE;OACf,eAAc,MACZ,qBAAAA,YAAA,EAAA,UAAA,CACE,oBAAC,qBAAD,EAAqB,OAAO,EAAI,CAAA,GAC/B,EAAE,UAAU,UAAU,MACrB,qBAAC,QAAD;QAAM,WAAU;QAAhB,UAAA;SACG,IAAI,kBAAkB,CAAC,CAAC,CAAC,EAAE,EAAE;SAAM;SAAG;SAAM;QACzC;OAER,CAAA,CAAA,EAAA,CAAA;OAEJ,WAAU;MACX,CAAA;MAEF,SAAS,cACR,oBAAC,qBAAD;OACE,cAAW;OACX,SAAQ,MAAK,EAAE;OACf,eAAc,MAAK,EAAE;OACrB,WAAU;MACX,CAAA;MAEF,SAAS,WAAW,UAAU,cAC7B,oBAAC,qBAAD;OACE,cAAW;OACX,wBAAsB,UAAU,UAAU,KAAA;OAC1C,SAAQ,MAAK,EAAE;OACf,eAAc,WAAU,oBAAC,sBAAD,EAA8B,OAAS,CAAA;OAC/D,aAAY,MAAK,UAAU,UAAU,UAAU,SAAS,SAAS,EAAE,KAAK;OACxE,WAAW,UAAU;OACrB,OAAO,UAAU;OACjB,WACE,UAAU,gBAAgB,mDAAmD;MAEhF,CAAA;MAEF,SAAS,WAAW,CAAC,UAAU,kBAC9B,qBAAC,OAAD;OAAK,WAAU;OAAf,UAAA,CACE,oBAAC,KAAD;QAAK,SAAQ;QAAU,MAAK;QAAQ,UAAA;OAE/B,CAAA,GACL,qBAAC,QAAD;QACE,MAAK;QACL,SAAQ;QACR,UAAU,CAAC,UAAU;QACrB,cAAa,MAAK,EAAE,eAAe;QACnC,eAAe,UAAU,eAAe;QAL1C,UAAA,CAMC,SAEC,oBAAC,KAAD;SAAK,MAAK;SAAK,UAAA;QAAM,CAAA,CACf;OACL,CAAA,CAAA;;MAEN,SAAS,WAAW,UAAU,UAC7B,oBAAC,OAAD;OAAK,WAAU;OACb,UAAA,qBAAC,QAAD;QACE,MAAK;QACL,SAAQ;QACR,cAAa,MAAK,EAAE,eAAe;QACnC,eAAe,UAAU,WAAW;QAJtC,UAAA,CAKC,QAEC,oBAAC,KAAD;SAAK,MAAK;SAAM,UAAA;QAAmB,CAAA,CAC7B;;MACL,CAAA;KAEgB;;GACG,CAAA;EACN,CAAA,CACJ;CACxB,CAAA,EAAA,CAAA;AAEN;;;ACvcA,SAAgB,iBAAiB,IAAY,SAAkB,SAA8C;CAC3G,MAAM,EAAE,iBAAiB,oBAAoB;CAC7C,gBAAgB;EACd,MAAM,OAAO,QAAQ;EACrB,IAAI,CAAC,WAAW,CAAC,MAAM;EACvB,MAAM,aAAa,OAAO,KAAK,kBAAkB,aAAa,KAAK,cAAc,EAAE,SAAS,KAAK,CAAC,IAAI,CAAC;EACvG,IAAI,WAAW,WAAW,GAAG;GAC3B,aAAa,EAAE;GACf;EACF;EACA,IAAI,YAAY;EAChB,QAAQ,IAAI,WAAW,KAAI,cAAa,UAAU,QAAQ,CAAC,CAAC,CACzD,WAAW;GACV,IAAI,CAAC,WAAW,aAAa,EAAE;EACjC,CAAC,CAAC,CACD,YAAY,CAAC,CAAC;EACjB,aAAa;GACX,YAAY;EACd;CACF,GAAG;EAAC;EAAS;EAAI;EAAc;CAAO,CAAC;AACzC;;ACVA,IAAM,iBACJ;;AASF,SAAgB,qBAAqB,EAAE,SAAS,OAAO,aAAwC;CAC7F,MAAM,MAAM,oBAAoB;CAChC,MAAM,OAAuB,UAAU,QAAQ,OAAO;CACtD,OACE,oBAAC,UAAD;EACE,MAAK;EACL,aAAU;EACV,cAAY;EACZ,cAAY,eAAe,MAAM,cAAc;EAC/C,OAAO,aAAa;EACpB,WAAW,GACT,gBACA,oFACA,uGACA,SACF;EACA,eAAe,IAAI,SAAS,SAAS,IAAI;EAExC,UAAA;CACK,CAAA;AAEZ;;AAGA,SAAS,qBAAqB,EAAE,SAAS,SAAqD;CAC5F,MAAM,MAAM,oBAAoB;CAChC,OACE,oBAAC,OAAD;EACE,MAAK;EACL,cAAW;EACX,WAAU;EAER,UAAA,CAAC,OAAO,IAAI,CAAC,CAAW,KAAI,UAC5B,oBAAC,UAAD;GAEE,MAAK;GACL,MAAK;GACL,gBAAc,UAAU;GACxB,cAAY,aAAa;GACzB,WAAW,GACT,4FACA,+BACA,UAAU,QAAQ,kCAAkC,6CACtD;GACA,eAAe,UAAU,SAAS,IAAI,SAAS,SAAS,KAAK;GAE5D,UAAA;EACK,GAbD,KAaC,CACT;CACE,CAAA;AAET;;;;;;;;AAmBA,SAAgB,qBAAqB,EACnC,OACA,OACA,UACA,cAAc,gBACd,aAC4B;CAC5B,MAAM,MAAM,oBAAoB;CAChC,MAAM,eAAe,OAA0B,IAAI;CACnD,MAAM,iBAAiB,OAAO,KAAK;CACnC,MAAM,WAAW,IAAI,gBAAgB,MAAM;CAC3C,MAAM,UAAU,QAAQ,IAAI;CAG5B,gBAAgB;EACd,IAAI,YAAY,CAAC,eAAe,SAAS;EACzC,eAAe,UAAU;EACzB,aAAa,SAAS,MAAM;CAC9B,GAAG,CAAC,QAAQ,CAAC;CAEb,MAAM,OAAoB,CAAC;CAC3B,MAAM,aAAa,QACjB,KAAK,WAAW,IACd,oBAAC,QAAD;EAA2B,WAAW;EAAgB,UAAA;CAEhD,GAFK,GAAG,IAAI,OAEZ,IAEN,oBAAC,sBAAD;EAA2C,SAAS,MAAM;EAAI,OAAO,MAAM;CAAQ,GAAxD,GAAG,IAAI,OAAiD;CAEvF,KAAK,MAAM,QAAQ,MAAM,OACvB,KAAK,KACH,qBAAC,UAAD,EAAA,UAAA,CACG,UAAU,KAAK,EAAE,GACjB,iBAAiB,IAAI,IACpB,oBAAC,iBAAD;EAAiB,OAAO;EAAM,OAAO,QAAQ;CAAI,CAAA,IAEjD,oBAAC,eAAD;EAAe,MAAM;EAAM,WAAU;CAAS,CAAA,CAExC,EAAA,GAPK,KAAK,EAOV,CACZ;CAEF,IAAI,IAAI,SAAS,IAAI,MAAM,YAAY,MAAM,IAAI;EAC/C,MAAM,EAAE,IAAI,SAAS,aAAa,OAAO,IAAI;EAC7C,KAAK,KACH,qBAAC,UAAD,EAAA,UAAA,CACG,UAAU,EAAE,GACb,oBAAC,eAAD;GAAe,OAAA;GAAM,MAAM;IAAE;IAAI;IAAS;IAAY,OAAO;GAAG;GAAG,WAAU;EAAS,CAAA,CAC9E,EAAA,GAHK,EAGL,CACZ;CACF;CACA,IAAI,UACF,KAAK,KACH,qBAAC,UAAD,EAAA,UAAA,CACG,UAAU,OAAO,GAClB,oBAAC,gBAAD;EACE,SAAS,MAAM;EACf,aAAY;EACZ,eAAe;GACb,eAAe,UAAU;EAC3B;CACD,CAAA,CACO,EAAA,GATI,OASJ,CACZ;CAGF,OACE,qBAAC,OAAD;EACE,aAAU;EACV,cAAY;EACZ,MAAK;EACL,cAAY,0BAA0B,MAAM;EAC5C,WAAW,GAAG,yBAAyB,SAAS;EALlD,UAAA,CAOG,KAAK,SAAS,KACb,oBAAC,OAAD;GAAK,WAAU;GAAyE,UAAA;EAAU,CAAA,GAEpG,qBAAC,OAAD;GACE,aAAU;GACV,WAAW,GAAG,sCAAsC,KAAK,SAAS,KAAK,wBAAwB;GAFjG,UAAA;IAIG,CAAC,YACA,oBAAC,QAAD;KACE,KAAK;KACL,SAAQ;KACR,MAAK;KACL,MAAM,oBAAC,UAAD,CAAW,CAAA;KACjB,eAAe,IAAI,eAAe,MAAM,EAAE;KAC3C,UAAA;IAEO,CAAA;IAEV,oBAAC,QAAD;KACE,SAAQ;KACR,MAAK;KACL,MAAM,oBAAC,gBAAD,CAAiB,CAAA;KACvB,WAAU;KACV,SAAS,UAAU,KAAA,IAAY,mBAAmB,IAAI,SAAS;KAC/D,UAAU,CAAC;KACX,eAAe,IAAI,SAAS,MAAM,IAAI,MAAM,UAAU,QAAQ,OAAO,KAAK;KAC3E,UAAA;IAEO,CAAA;IACP,YACC,oBAAC,QAAD;KACE,SAAQ;KACR,MAAK;KACL,MAAM,oBAAC,YAAD,CAAa,CAAA;KACnB,WAAU;KACV,cAAY;KACZ,SAAS;KACV,UAAA;IAEO,CAAA;GAEP;EACF,CAAA,CAAA;;AAET;AAEA,SAAS,gBAAgB,EAAE,OAAO,SAAmD;CACnF,MAAM,MAAM,oBAAoB;CAChC,MAAM,UAAU,OAAuB,IAAI;CAC3C,MAAM,UAAU,IAAI,QAAQ,IAAI,MAAM,EAAE;CACxC,iBAAiB,MAAM,IAAI,SAAS,OAAO;CAC3C,MAAM,QAAQ,YAAY,KAAK;CAE/B,OACE,qBAAC,OAAD;EACE,KAAK;EACL,aAAU;EACV,gBAAc,WAAW,KAAA;EACzB,eAAa,WAAW,KAAA;EACxB,WAAW,GACT,mFACA,WAAW,qBACb;EARF,UAAA,CAUE,qBAAC,OAAD;GAAK,WAAU;GAAf,UAAA;IACE,oBAAC,YAAD,EAAY,WAAU,iCAAkC,CAAA;IACxD,oBAAC,KAAD;KAAK,IAAG;KAAO,SAAQ;KAAQ,MAAK;KAAM,UAAA;IAErC,CAAA;IACL,qBAAC,KAAD;KAAK,IAAG;KAAO,SAAQ;KAAQ,MAAK;KAApC,UAAA;MAA4C;MACvC;MAAM;MAAE,UAAU,IAAI,cAAc;KACpC;;IACL,qBAAC,OAAD;KAAK,WAAU;KAAf,UAAA,CACE,oBAAC,sBAAD;MAAsB,SAAS,MAAM;MAAI,OAAO,MAAM;KAAQ,CAAA,GAC9D,oBAAC,QAAD;MACE,SAAQ;MACR,MAAK;MACL,SAAQ;MACR,UAAU;MACV,eAAe,IAAI,YAAY,MAAM,EAAE;MAEvC,UAAA,oBAAC,YAAD,CAAa,CAAA;KACP,CAAA,CACL;;GACF;EACL,CAAA,GAAA,oBAAC,sBAAD;GAA6B;GAAc;EAAQ,CAAA,CAChD;;AAET;;;;;;ACxOA,SAAgB,sBAAsB,EAAE,OAAO,aAAyC;CACtF,MAAM,MAAM,oBAAoB;CAChC,MAAM,CAAC,WAAW,eAAe,CAAC,IAAI,OAAO;CAC7C,MAAM,UAAU,OAAuB,IAAI;CAC3C,MAAM,aAAa,OAA0B,IAAI;CACjD,MAAM,UAAU,IAAI,QAAQ,IAAI,MAAM,EAAE;CACxC,MAAM,OAAO,IAAI,gBAAgB,MAAM;CACvC,MAAM,QAAQ,YAAY,KAAK;CAE/B,MAAM,iBAAiB,IAAI,MAAM,WAAU,SAAQ,QAAQ,OAAO,KAAK,EAAE,CAAC;CAC1E,MAAM,QAAQ,mBAAmB,KAAK,IAAI,MAAM,SAAS;CACzD,iBAAiB,MAAM,IAAI,SAAS,OAAO;CAE3C,MAAM,iBAAiB,UAAyC;EAC9D,IAAI,SAAS;EACb,MAAM,WAAW,MAAM,KAAK,QAAQ,SAAS,iBAA8B,2BAA2B,KAAK,CAAC,CAAC;EAC7G,MAAM,UAAU,SAAS,WAAU,OAAM,OAAO,MAAM,MAAM;EAC5D,IAAI,YAAY,IAAI;EACpB,QAAQ,MAAM,KAAd;GACE,KAAK,cAAc;IACjB,MAAM,eAAe;IACrB,MAAM,OAAO,SAAS,UAAU;IAChC,IAAI,MAAM,KAAK,MAAM;SAChB,IAAI,CAAC,IAAI,UAAU,QAAQ,OAAO,GAAG,OAAO,GAAG,IAAI,WAAW;IACnE;GACF;GACA,KAAK,aAAa;IAChB,MAAM,eAAe;IACrB,MAAM,OAAO,SAAS,UAAU;IAChC,IAAI,MAAM,KAAK,MAAM;SAChB,IAAI,UAAU,QAAQ,GAAG,IAAI,QAAQ;IAC1C;GACF;GACA,KAAK;GACL,KAAK;IACH,MAAM,eAAe;IACrB,OAAO;EAGX;CACF;CAEA,MAAM,eAAe;EACnB,IAAI,YAAY,MAAM,EAAE;EACxB,IAAI,iBAAiB,KAAK;CAC5B;CAEA,OACE,qBAAC,SAAD;EAAe;EAAM,eAAc,SAAQ,IAAI,aAAa,OAAO,MAAM,KAAK,IAAI;EAAlF,UAAA,CACE,qBAAC,OAAD;GACE,KAAK;GACL,MAAK;GACL,cAAY,oBAAoB,MAAM,GAAG,UAAU,IAAI,cAAc;GACrE,eAAa,WAAW,KAAA;GACxB,aAAU;GACV,gBAAc,WAAW,KAAA;GACzB,gBAAc,WAAW,KAAA;GACzB,WAAW,GAAG,uBAAuB,WAAW,WAAW,uBAAuB,SAAS;GAC3F,WAAW;GATb,UAAA,CAWE,qBAAC,gBAAD;IACE,MAAK,OAAM;KACT,WAAW,UAAU;KACrB,IAAI,gBAAgB,MAAM,IAAI,SAAS,UAAU,OAAO,EAAE;IAC5D;IACA,QAAQ,oBAAC,UAAD,EAAQ,MAAK,SAAU,CAAA;IAC/B,2BAAwB;IACxB,WAAW;IACX,OAAM;IARR,UAAA;KAUE,oBAAC,YAAD,EAAY,eAAA,KAAa,CAAA;KACzB,oBAAC,QAAD;MAAM,WAAU;MAAW,UAAA;KAAqB,CAAA;KAC/C,QAAQ,KACP,oBAAC,KAAD;MAAK,IAAG;MAAO,SAAQ;MAAS,MAAK;MAAQ,eAAA;MAC1C,UAAA;KACE,CAAA;IAEO;GACf,CAAA,GAAA,UACC,oBAAC,QAAD;IAAM,eAAA;IAAY,WAAW;IAC3B,UAAA,oBAAC,OAAD,CAAQ,CAAA;GACJ,CAAA,IAEN,oBAAC,UAAD;IACE,MAAK;IACL,MAAK,OAAM,IAAI,gBAAgB,MAAM,IAAI,UAAU,EAAE;IACrD,2BAAwB;IACxB,cAAW;IACX,OAAM;IACN,WAAW;IACX,SAAS;IAET,UAAA,oBAAC,OAAD,CAAQ,CAAA;GACF,CAAA,CAEP;EACL,CAAA,GAAA,qBAAC,gBAAD;GACE,OAAM;GACN,WAAU;IACH,wBAAwB;GAC/B,YAAY;GAJd,UAAA,CAME,qBAAC,OAAD;IAAK,WAAU;IAAf,UAAA;KACE,oBAAC,YAAD,EAAY,WAAU,iCAAkC,CAAA;KACxD,oBAAC,KAAD;MAAK,IAAG;MAAO,SAAQ;MAAQ,MAAK;MAAM,UAAA;KAErC,CAAA;KACL,oBAAC,KAAD;MAAK,IAAG;MAAO,SAAQ;MAAS,MAAK;MAAQ,WAAU;MACpD,UAAA;KACE,CAAA;KACL,oBAAC,QAAD;MACE,SAAQ;MACR,MAAK;MACL,WAAU;MACV,SAAQ;MACR,eAAe,IAAI,aAAa,IAAI;MAEpC,UAAA,oBAAC,OAAD,CAAQ,CAAA;KACF,CAAA;IACL;GACL,CAAA,GAAA,oBAAC,sBAAD;IACS;IACP,OAAO;IACP,aAAY;IACZ,gBAAgB;KACd,IAAI,aAAa,IAAI;KACrB,OAAO;IACT;GACD,CAAA,CACa;EACT,CAAA,CAAA;;AAEb;AAEA,IAAM,WAAW,OAAuB,WACtC,MAAM,MAAM,MAAK,SAAS,KAAK,OAAO,SAAS,OAAO,UAAU,QAAQ,QAAQ,MAAM,MAAM,CAAE;;;AC1JhG,SAAgB,eAAe,EAAE,SAA4B;CAC3D,MAAM,MAAM,oBAAoB;CAChC,IAAI,CAAC,IAAI,mBAAmB,OAAO;CACnC,OACE,oBAAC,oBAAD;EACS;EACP,UAAS,UAAS;GAChB,MAAM,gBAAgB;GACtB,IAAI,MAAM;GACV,IAAI,WAAW;EACjB;CACD,CAAA;AAEL;;ACkCA,SAAS,iBAAiB,EACxB,WACA,YACA,YAKC;CACD,MAAM,MAAM,oBAAoB;CAChC,OACE,qBAAC,OAAD;EACE,MAAK;EACL,cAAY,IAAI;EAChB,aAAU;GACH,wBAAwB;EAC/B,WAAW,GAIT,8CACA,SACF;EAXF,UAAA;GAaG;GACD,oBAAC,QAAD;IAAM,WAAU;IACd,UAAA,oBAAC,gBAAD,EAAgB,OAAO,WAAa,CAAA;GAChC,CAAA;GACN,oBAAC,gBAAD;IAAgB,aAAU;IAAU,UAAA,IAAI;GAA6B,CAAA;EAClE;;AAET;;;;;;;;;;;;;;;;;AAkBA,SAAgB,UAAU,EACxB,QACA,WACA,OACA,eACA,cACA,UACA,cAAc,YAAY,WAC1B,0BACA,aAAa,iBACb,WACA,YACiB;CACjB,OACE,oBAAC,mBAAD;EACU;EACG;EACJ;EACQ;EACD;EACJ;EACC;EACe;EAE1B,UAAA,oBAAC,kBAAD;GAA6B;GAAuB;GACjD;EACe,CAAA;CACD,CAAA;AAEvB;;;;;;AAOA,SAAgB,eAAe,EAAE,aAAa,qBAA0C;CACtF,MAAM,MAAM,oBAAoB;CAGhC,MAAM,QAAqB,CAAC;CAC5B,KAAK,MAAM,QAAQ,IAAI,WAAW,OAAO;EACvC,MAAM,OAAO,iBAAiB,IAAI,IAAI,oBAAC,uBAAD,EAAuB,OAAO,KAAO,CAAA,IAAI,WAAW,IAAI;EAC9F,IAAI,SAAS,MAAM,MAAM,KAAK,oBAAC,UAAD,EAAA,UAAyB,KAAe,GAAzB,KAAK,EAAoB,CAAC;CACzE;CACA,IAAI,IAAI,SAAS,CAAC,IAAI,MAAM,SAAS;EAEnC,MAAM,EAAE,IAAI,SAAS,aAAa,OAAO,IAAI;EAC7C,MAAM,KACJ,oBAAC,UAAD,EAAA,UACE,oBAAC,eAAD;GAAe,OAAA;GAAM,MAAM;IAAE;IAAI;IAAS;IAAY,OAAO;GAAG;EAAI,CAAA,EAC5D,GAFK,EAEL,CACZ;CACF;CACA,OAAO,oBAAAC,YAAA,EAAA,UAAG,MAAQ,CAAA;AACpB;AAUA,IAAM,qBAAqB,SAAwB,oBAAC,eAAD,EAAqB,KAAO,CAAA;AAE/E,UAAU,QAAQ;AAClB,UAAU,OAAO;AACjB,UAAU,eAAe;AACzB,UAAU,QAAQ;AAClB,UAAU,YAAY;;;ACxKtB,IAAa,2BAAgD;CAC3D;EAAE,IAAI;EAAM,OAAO;EAAM,UAAU;CAAK;CACxC;EAAE,IAAI;EAAU,OAAO;CAAS;CAChC;EAAE,IAAI;EAAY,OAAO;CAAW;CACpC;EAAE,IAAI;EAAgB,OAAO;CAAmB;CAChD;EAAE,IAAI;EAAe,OAAO;CAAc;CAC1C;EAAE,IAAI;EAAM,OAAO;CAAI;CACvB;EAAE,IAAI;EAAM,OAAO;CAAI;CACvB;EAAE,IAAI;EAAO,OAAO;CAAK;CACzB;EAAE,IAAI;EAAO,OAAO;CAAK;CACzB;EAAE,IAAI;EAAY,OAAO;EAAY,OAAO;CAAO;CACnD;EAAE,IAAI;EAAgB,OAAO;EAAgB,OAAO;CAAO;CAC3D;EAAE,IAAI;EAAM,OAAO;EAAM,OAAO;CAAO;AACzC"}
@@ -8,11 +8,11 @@ const require_Txt = require("./Txt-BnoSqxKE.cjs");
8
8
  const require_primitives_password_manager_autofill = require("./primitives/password-manager-autofill.cjs.js");
9
9
  const require_components_Kbd = require("./components/Kbd.cjs.js");
10
10
  const require_popover = require("./popover-BJqa6Hz6.cjs");
11
- const require_combobox_parts = require("./combobox-parts-ScKcYjMR.cjs");
11
+ const require_combobox_parts = require("./combobox-parts-C4phOq4t.cjs");
12
12
  const require_types = require("./types-CP7wbYua.cjs");
13
- const require_filter_bar_chip = require("./filter-bar-chip-CIEsWcEw.cjs");
13
+ const require_filter_bar_chip = require("./filter-bar-chip-Cg-UbIwP.cjs");
14
14
  const require_hooks_use_keyboard_shortcut_label = require("./hooks/use-keyboard-shortcut-label.cjs.js");
15
- const require_filter_bar_time_range = require("./filter-bar-time-range-DvuaFnkI.cjs");
15
+ const require_filter_bar_time_range = require("./filter-bar-time-range-BA-pXMlo.cjs");
16
16
  const require_clear_filters_button = require("./clear-filters-button-Buc973vw.cjs");
17
17
  let react = require("react");
18
18
  let react_jsx_runtime = require("react/jsx-runtime");
@@ -39,7 +39,7 @@ function FilterBarInput(props) {
39
39
  if (require_filter_bar_chip.useFilterBarContext().inputTarget !== props.groupId) return null;
40
40
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FilterBarInputImpl, { ...props });
41
41
  }
42
- function FilterBarInputImpl({ placeholder = "Filter…", className, "aria-label": ariaLabel = "Add filter", groupId, onLeave }) {
42
+ function FilterBarInputImpl({ placeholder = "Filter", className, "aria-label": ariaLabel = "Add filter", groupId, onLeave }) {
43
43
  const ctx = require_filter_bar_chip.useFilterBarContext();
44
44
  const container = require_primitives_portal_container.usePortalContainer();
45
45
  const inputRef = (0, react.useRef)(null);
@@ -216,7 +216,7 @@ function FilterBarInputImpl({ placeholder = "Filter…", className, "aria-label"
216
216
  };
217
217
  const items = emptyForStepChange ? EMPTY_ITEMS : optionsForStep[step];
218
218
  const filterItem = (0, react.useCallback)((item, text, itemToString) => "search" in item && item.search === true || require_filter_bar_chip.matchesQueryFilter(item, text, itemToString), []);
219
- const inputPlaceholder = step === "field" ? placeholder : step === "operator" ? "Operator…" : valueStep.hasSuggestions && valueStep.allowFreeText ? "Search or type a value…" : field?.type === "number" ? "Number…" : "Value…";
219
+ const inputPlaceholder = step === "field" ? placeholder : step === "operator" ? "Operator" : valueStep.hasSuggestions && valueStep.allowFreeText ? "Search or type a value" : field?.type === "number" ? "Number" : "Value";
220
220
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_jsx_runtime.Fragment, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_base_ui_react_combobox.Combobox.Root, {
221
221
  items,
222
222
  itemToStringLabel: getItemLabel,
@@ -457,7 +457,7 @@ function FilterBarGroupEditor({ group, depth, onRemove, removeLabel = "Remove gr
457
457
  }
458
458
  if (targeted) rows.push(/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react.Fragment, { children: [connector("input"), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FilterBarInput, {
459
459
  groupId: group.id,
460
- placeholder: "Add condition…",
460
+ placeholder: "Add condition",
461
461
  onLeave: () => {
462
462
  focusAddFilter.current = true;
463
463
  }
@@ -900,4 +900,4 @@ Object.defineProperty(exports, "FilterBarLogicToggle", {
900
900
  }
901
901
  });
902
902
 
903
- //# sourceMappingURL=FilterBar-Buw0tv51.cjs.map
903
+ //# sourceMappingURL=FilterBar-CQl04O6t.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FilterBar-CQl04O6t.cjs","names":["BracesIcon","useFilterBarContext","usePortalContainer","useRef","useState","useIsApplePlatform","useMemo","findGroup","useCallback","parseFieldValue","useValueStep","matchesQueryFilter","_Fragment","ComboboxPrimitive","alwaysHighlightProps","cn","comboboxTriggerClass","inputFocusBorderWithin","ListFilterIcon","passwordManagerOptOutProps","unstyledFormElementStyle","FLOATING_POSITION_METHOD","comboboxStyles","FilterBarOptionList","FilterBarFieldLabel","FilterBarOptionLabel","Txt","Button","Kbd","useFilterBarContext","useFilterBarContext","cn","useRef","Fragment","isFilterBarGroup","FilterBarChip","Button","PlusIcon","FolderPlusIcon","Trash2Icon","countLeaves","FolderIcon","Txt","useFilterBarContext","useState","useRef","countLeaves","Popover","cn","chipClass","PopoverTrigger","editableSegmentClass","BracesIcon","Txt","removeSegmentClass","XIcon","PopoverContent","FILTER_BAR_SCOPE_ATTR","Button","useFilterBarContext","ClearFiltersButton","useFilterBarContext","FILTER_BAR_SCOPE_ATTR","cn","VisuallyHidden","FilterBarProvider","isFilterBarGroup","Fragment","FilterBarChip","_Fragment","FilterBarTimeRange"],"sources":["../src/ds/components/FilterBar/filter-bar-input.tsx","../src/ds/components/FilterBar/use-settle-on-leave.ts","../src/ds/components/FilterBar/filter-bar-group-editor.tsx","../src/ds/components/FilterBar/filter-bar-advanced-chip.tsx","../src/ds/components/FilterBar/filter-bar-clear.tsx","../src/ds/components/FilterBar/filter-bar.tsx","../src/ds/components/FilterBar/default-operators.ts"],"sourcesContent":["import type { BaseUIEvent } from '@base-ui/react/types';\nimport { BracesIcon, ListFilterIcon } from 'lucide-react';\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport type { KeyboardEvent } from 'react';\nimport { flushSync } from 'react-dom';\nimport { FILTER_BAR_CONTROL_SIZE, FilterBarFieldLabel, alwaysHighlightProps } from './filter-bar-chip';\nimport { useFilterBarContext } from './filter-bar-context';\nimport { FilterBarOptionLabel, FilterBarOptionList } from './filter-bar-option-list';\nimport { findGroup } from './filter-bar-tree';\nimport { matchesQueryFilter } from './match-query';\nimport type { FilterBarDraft, FilterBarField, FilterBarOperator, FilterBarOption, FilterBarValue } from './types';\nimport { parseFieldValue } from './types';\nimport { useValueStep } from './use-value-step';\nimport { Button } from '@/ds/components/Button/Button';\nimport { ComboboxPrimitive, comboboxStyles } from '@/ds/components/Combobox';\nimport { comboboxTriggerClass } from '@/ds/components/Combobox/combobox-styles';\nimport { Kbd } from '@/ds/components/Kbd/kbd';\nimport { Txt } from '@/ds/components/Txt';\nimport { FLOATING_POSITION_METHOD } from '@/ds/primitives/floating';\nimport { inputFocusBorderWithin, unstyledFormElementStyle } from '@/ds/primitives/form-element';\nimport { MENU_SIDE_OFFSET } from '@/ds/primitives/menu-item';\nimport { passwordManagerOptOutProps } from '@/ds/primitives/password-manager-autofill';\nimport { usePortalContainer } from '@/ds/primitives/portal-container';\nimport { useIsApplePlatform } from '@/hooks/use-keyboard-shortcut-label';\nimport { cn } from '@/lib/utils';\n\ntype Step = 'field' | 'operator' | 'value';\n\ntype Item = FilterBarField | FilterBarOperator | FilterBarOption;\n\nconst getItemLabel = (item: Item) => ('label' in item && item.label ? item.label : 'value' in item ? item.value : '');\n\nconst EMPTY_ITEMS: readonly Item[] = [];\n/** Pinned last entry of the field list that spawns an advanced filter (an `or` group) instead of a filter. */\nconst ADVANCED_FIELD_ID = '__filter-bar-advanced__';\nconst ADVANCED_FIELD: FilterBarField = {\n id: ADVANCED_FIELD_ID,\n label: 'Advanced filter…',\n icon: BracesIcon,\n operators: [],\n};\n\nexport type FilterBarInputProps = {\n placeholder?: string;\n className?: string;\n 'aria-label'?: string;\n /**\n * Group this instance commits into; omit for the bar's own input. Only the instance whose\n * `groupId` matches the provider's `inputTarget` renders, so a single input is ever mounted.\n */\n groupId?: string;\n /** Called when Escape is pressed on an empty query inside a group, after the input hands back to the bar. */\n onLeave?: () => void;\n};\n\n/**\n * Typeahead entry point: type to pick a field, then an operator, then a value.\n * Focus never leaves the input; the popup is driven with the arrow keys.\n */\nexport function FilterBarInput(props: FilterBarInputProps) {\n const ctx = useFilterBarContext();\n if (ctx.inputTarget !== props.groupId) return null;\n return <FilterBarInputImpl {...props} />;\n}\n\nfunction FilterBarInputImpl({\n placeholder = 'Filter',\n className,\n 'aria-label': ariaLabel = 'Add filter',\n groupId,\n onLeave,\n}: FilterBarInputProps) {\n const ctx = useFilterBarContext();\n const container = usePortalContainer();\n const inputRef = useRef<HTMLInputElement | null>(null);\n const anchorRef = useRef<HTMLDivElement>(null);\n const [open, setOpen] = useState(false);\n const [query, setQuery] = useState('');\n const [highlighted, setHighlighted] = useState<Item | null>(null);\n const [emptyForStepChange, setEmptyForStepChange] = useState(false);\n const modEnterLabel = useIsApplePlatform() ? '⌘↵' : 'Ctrl ↵';\n\n // The draft lives in the provider so the chip list can render it; the step follows from it.\n const { draft, setDraft: setDraftState, commitDraft } = ctx;\n const step: Step = !draft ? 'field' : !draft.operatorId ? 'operator' : 'value';\n const field = draft ? ctx.getField(draft.fieldId) : undefined;\n const fieldOperators = useMemo(() => (field ? ctx.getFieldOperators(field) : []), [ctx, field]);\n const operator = draft?.operatorId\n ? (fieldOperators.find(o => o.id === draft.operatorId) ?? ctx.getOperator(draft.operatorId))\n : undefined;\n // The advanced option lives in the bar only; inside a popover, nesting is the editor's `+ Group`.\n const offerAdvanced = ctx.groupsEnabled && groupId === undefined;\n const visibleFields = useMemo(() => {\n const fields = ctx.fields.filter(f => !f.hidden);\n return offerAdvanced ? [...fields, ADVANCED_FIELD] : fields;\n }, [ctx.fields, offerAdvanced]);\n const targetGroup = groupId ? findGroup(ctx.expression, groupId) : undefined;\n\n // A group's input mounts on demand (see `openGroupInput`) and takes focus itself.\n useEffect(() => {\n if (groupId) inputRef.current?.focus();\n }, [groupId]);\n\n // Base UI owns the highlight index and keeps it when the list content changes, so a row\n // reached with ArrowDown would carry over into the step that follows. An empty list committed\n // first drops that index, and `autoHighlight` re-anchors on the first row of the new step.\n const withHighlightReset = useCallback((change: () => void) => {\n flushSync(() => setEmptyForStepChange(true));\n change();\n setEmptyForStepChange(false);\n }, []);\n\n const setDraft = useCallback(\n (next: Omit<FilterBarDraft, 'id' | 'from'> | null) => withHighlightReset(() => setDraftState(next)),\n [withHighlightReset, setDraftState],\n );\n\n const reset = useCallback(() => {\n setDraftState(null);\n setQuery('');\n }, [setDraftState]);\n\n const close = useCallback(() => {\n setOpen(false);\n reset();\n }, [reset]);\n\n const commit = useCallback(\n (fieldId: string, operatorId: string, value: FilterBarValue) => {\n withHighlightReset(() => commitDraft({ fieldId, operatorId }, value));\n setQuery('');\n inputRef.current?.focus();\n },\n [withHighlightReset, commitDraft],\n );\n\n const selectOperator = useCallback(\n (fieldId: string, next: FilterBarOperator) => {\n if (next.arity === 'none') {\n commit(fieldId, next.id, '');\n return;\n }\n setDraft({ fieldId, operatorId: next.id });\n setQuery('');\n },\n [commit, setDraft],\n );\n\n const selectField = useCallback(\n (next: FilterBarField) => {\n if (next.id === ADVANCED_FIELD_ID) {\n // `or` is the useful default: an `and` group is indistinguishable from the root.\n const id = ctx.addGroup(undefined, 'or');\n ctx.setOpenGroup(id);\n ctx.openGroupInput(id);\n setQuery('');\n setOpen(false);\n return;\n }\n const [only, ...rest] = ctx.getFieldOperators(next);\n // Free-text entry with text already typed: that text is the value, so neither the\n // operator nor the value step has anything left to ask.\n if (next.search && only && query.trim() !== '') {\n commit(next.id, only.id, parseFieldValue(next.type, query));\n return;\n }\n // A single allowed operator is implied: skip straight to the value step.\n if (only && rest.length === 0) {\n selectOperator(next.id, only);\n return;\n }\n setDraft({ fieldId: next.id });\n setQuery('');\n },\n [ctx, commit, query, selectOperator, setDraft],\n );\n\n const valueStep = useValueStep({\n field,\n operator,\n query,\n enabled: open && step === 'value',\n setQuery,\n onCommit: value => {\n if (draft?.operatorId) commit(draft.fieldId, draft.operatorId, value);\n },\n });\n\n // Leaving a group's input hands the target back to the bar; empty groups are pruned when the\n // popover closes, never here.\n const leaveGroup = useCallback(() => {\n if (!groupId) return false;\n ctx.openGroupInput(undefined);\n onLeave?.();\n return true;\n }, [ctx, groupId, onLeave]);\n\n const stepBack = useCallback(() => {\n if (step === 'value' && draft) {\n // Back to the field step when the operator was implied (single operator).\n const skipOperator = field ? fieldOperators.length === 1 : false;\n setDraft(skipOperator ? null : { fieldId: draft.fieldId });\n } else if (step === 'operator') setDraft(null);\n else if (!leaveGroup()) setOpen(false);\n setQuery('');\n }, [step, draft, field, fieldOperators, setDraft, leaveGroup]);\n\n // Selection is routed per step and never kept by Base UI (`value` stays null).\n const handleSelect = (item: Item) => {\n if (step === 'field') selectField(item as FilterBarField);\n else if (step === 'operator' && draft) selectOperator(draft.fieldId, item as FilterBarOperator);\n else valueStep.handleSelect(item as FilterBarOption);\n };\n\n // App-level keys run before Base UI's own input handling.\n const handleKeyDown = (event: BaseUIEvent<KeyboardEvent<HTMLInputElement>>) => {\n if (event.key === 'Escape') {\n event.preventDefault();\n // Consumed here: an enclosing popover (advanced filter) must not close on it.\n event.stopPropagation();\n event.preventBaseUIHandler();\n stepBack();\n return;\n }\n if (!open && (event.key === 'ArrowDown' || event.key === 'Enter')) {\n event.preventDefault();\n event.preventBaseUIHandler();\n setOpen(true);\n return;\n }\n if (query === '') {\n if (event.key === 'Backspace') {\n event.preventDefault();\n event.preventBaseUIHandler();\n if (step !== 'field') stepBack();\n else if (targetGroup) {\n // Inside a group: eat its last chip, or drop the group once it is empty.\n const last = targetGroup.nodes.findLast(node => !ctx.leaving.has(node.id));\n if (last) ctx.removeItem(last.id);\n else leaveGroup();\n } else {\n // Chips still animating out are already gone from the value: skip them.\n const last = ctx.items.findLast(item => !ctx.leaving.has(item.id));\n if (last) ctx.removeItem(last.id);\n }\n return;\n }\n if (event.key === 'ArrowLeft' && step === 'field') {\n if (ctx.focusChip(ctx.items.length - 1, -1, 'remove')) event.preventDefault();\n return;\n }\n }\n if (!open) return;\n\n if (event.key === 'Tab' && highlighted && step !== 'value' && (step === 'operator' || query !== '')) {\n event.preventDefault();\n event.preventBaseUIHandler();\n handleSelect(highlighted);\n return;\n }\n if (step === 'value') {\n const highlightedOption = valueStep.hasSuggestions ? (highlighted as FilterBarOption | null) : null;\n const handled = valueStep.handleKeyDown(event, highlightedOption);\n // Base UI closes on Enter when nothing is highlighted (form submission); the draft must stay open.\n if (handled || (event.key === 'Enter' && highlightedOption === null)) event.preventBaseUIHandler();\n }\n };\n\n const optionsForStep: Record<Step, readonly Item[]> = {\n field: visibleFields,\n operator: fieldOperators,\n value: valueStep.options,\n };\n const items: readonly Item[] = emptyForStepChange ? EMPTY_ITEMS : optionsForStep[step];\n\n // A search field is the way out for text that names no field, so it survives the field\n // step's own filtering whatever was typed; every other item matches on its label.\n const filterItem = useCallback(\n (item: Item, text: string, itemToString?: (item: Item) => string) =>\n ('search' in item && item.search === true) || matchesQueryFilter(item, text, itemToString),\n [],\n );\n\n const inputPlaceholder =\n step === 'field'\n ? placeholder\n : step === 'operator'\n ? 'Operator'\n : valueStep.hasSuggestions && valueStep.allowFreeText\n ? 'Search or type a value'\n : field?.type === 'number'\n ? 'Number'\n : 'Value';\n\n return (\n <>\n <ComboboxPrimitive.Root<Item>\n items={items}\n itemToStringLabel={getItemLabel}\n // The value step is already filtered (locally or server-side) by useValueSuggestions.\n filter={step === 'value' ? null : filterItem}\n value={null}\n onValueChange={(item, details) => {\n // Never let Base UI keep the selection, fill the input or close: each step routes it.\n details.cancel();\n if (item) handleSelect(item);\n }}\n inputValue={query}\n onInputValueChange={(next, details) => {\n if (details.reason !== 'input-change') return;\n setQuery(next);\n if (!open) setOpen(true);\n }}\n onItemHighlighted={item => setHighlighted(item ?? null)}\n open={open}\n onOpenChange={(next, details) => {\n // Escape is handled by the input (it steps back rather than closing).\n if (!next && details.reason === 'escape-key') return;\n // The input is the anchor, not a trigger: clicking it must keep the draft open.\n if (\n !next &&\n details.reason === 'outside-press' &&\n details.event.target instanceof Node &&\n inputRef.current?.contains(details.event.target)\n ) {\n return;\n }\n if (next) setOpen(true);\n else close();\n }}\n {...alwaysHighlightProps}\n modal={false}\n >\n <div\n ref={anchorRef}\n data-slot=\"filter-bar-input-trigger\"\n className={cn(\n // Same trigger recipe as every other DS Combobox (fill, radius, `[&>svg]` icon sizing\n // and the Button icon offset); the bar itself has no chrome. Focus lives on the\n // nested input, so the recipe's `focus-visible` border becomes `focus-within`.\n comboboxTriggerClass({ variant: 'default', size: FILTER_BAR_CONTROL_SIZE }),\n 'w-auto cursor-text',\n 'focus-within:bg-fill-hover',\n inputFocusBorderWithin,\n step === 'field' ? 'min-w-40' : 'min-w-28',\n className,\n )}\n >\n <ListFilterIcon aria-hidden className=\"shrink-0\" />\n <ComboboxPrimitive.Input\n ref={el => {\n inputRef.current = el;\n ctx.registerInput(el);\n }}\n aria-label={ariaLabel}\n spellCheck={false}\n {...passwordManagerOptOutProps}\n data-slot=\"filter-bar-input\"\n data-step={step}\n data-target={targetGroup?.id}\n inputMode={step === 'value' && field?.type === 'number' ? 'decimal' : undefined}\n placeholder={inputPlaceholder}\n className={cn(\n unstyledFormElementStyle,\n 'min-w-0 flex-1 bg-transparent',\n 'placeholder:text-muted-foreground placeholder:transition-opacity placeholder:duration-normal focus:placeholder:opacity-70',\n )}\n onFocus={() => setOpen(true)}\n onKeyDown={handleKeyDown}\n />\n </div>\n <ComboboxPrimitive.Portal container={container}>\n <ComboboxPrimitive.Positioner\n // Base UI anchors to the input, which starts after the filter icon; align with the pill instead.\n anchor={anchorRef}\n align=\"start\"\n sideOffset={MENU_SIDE_OFFSET}\n positionMethod={FLOATING_POSITION_METHOD}\n className={comboboxStyles.positioner}\n >\n <ComboboxPrimitive.Popup // Match the pill, with the DS Combobox's 11rem floor (replaces the menu's anchor-width minimum).\n className={cn(comboboxStyles.popup, 'w-(--anchor-width) min-w-44')}\n data-slot=\"filter-bar-editor\"\n >\n {step === 'field' && (\n <FilterBarOptionList<FilterBarField>\n aria-label=\"Fields\"\n getKey={f => f.id}\n renderOption={f => (\n <>\n <FilterBarFieldLabel field={f} />\n {f.search && query !== '' && (\n <span className=\"min-w-0 truncate text-muted-foreground\">\n {ctx.getFieldOperators(f)[0]?.label} \"{query}\"\n </span>\n )}\n </>\n )}\n emptyText=\"No matching field.\"\n />\n )}\n {step === 'operator' && (\n <FilterBarOptionList<FilterBarOperator>\n aria-label=\"Operators\"\n getKey={o => o.id}\n renderOption={o => o.label}\n emptyText=\"No matching operator.\"\n />\n )}\n {step === 'value' && valueStep.hasOptions && (\n <FilterBarOptionList<FilterBarOption>\n aria-label=\"Values\"\n aria-multiselectable={valueStep.isMany || undefined}\n getKey={o => o.value}\n renderOption={option => <FilterBarOptionLabel option={option} />}\n isSelected={o => valueStep.isMany && valueStep.selected.includes(o.value)}\n isLoading={valueStep.isLoading}\n error={valueStep.error}\n emptyText={\n valueStep.allowFreeText ? 'No suggestions — press Enter to use your text.' : 'No matching value.'\n }\n />\n )}\n {step === 'value' && !valueStep.hasSuggestions && (\n <div className=\"flex items-center justify-between gap-2 py-1 pr-1 pl-[.9em]\">\n <Txt variant=\"caption\" tone=\"muted\">\n Type a value\n </Txt>\n <Button\n size=\"sm\"\n variant=\"default\"\n disabled={!valueStep.canCommitQuery}\n onMouseDown={e => e.preventDefault()}\n onClick={() => valueStep.submitFreeText()}\n >\n Apply\n <Kbd size=\"xs\">↵</Kbd>\n </Button>\n </div>\n )}\n {step === 'value' && valueStep.isMany && (\n <div className=\"flex items-center justify-end gap-1 border-t border-border p-1\">\n <Button\n size=\"sm\"\n variant=\"default\"\n onMouseDown={e => e.preventDefault()}\n onClick={() => valueStep.commitDone()}\n >\n Done\n <Kbd size=\"xs\">{modEnterLabel}</Kbd>\n </Button>\n </div>\n )}\n </ComboboxPrimitive.Popup>\n </ComboboxPrimitive.Positioner>\n </ComboboxPrimitive.Portal>\n </ComboboxPrimitive.Root>\n </>\n );\n}\n","import { useEffect } from 'react';\nimport { useFilterBarContext } from './filter-bar-context';\n\n/** Keeps a leaving node in the DOM until its exit animation has played, then releases it. */\nexport function useSettleOnLeave(id: string, leaving: boolean, rootRef: React.RefObject<HTMLElement | null>) {\n const { settleRemove } = useFilterBarContext();\n useEffect(() => {\n const root = rootRef.current;\n if (!leaving || !root) return;\n const animations = typeof root.getAnimations === 'function' ? root.getAnimations({ subtree: true }) : [];\n if (animations.length === 0) {\n settleRemove(id);\n return;\n }\n let cancelled = false;\n Promise.all(animations.map(animation => animation.finished))\n .then(() => {\n if (!cancelled) settleRemove(id);\n })\n .catch(() => {});\n return () => {\n cancelled = true;\n };\n }, [leaving, id, settleRemove, rootRef]);\n}\n","import { FolderIcon, FolderPlusIcon, PlusIcon, Trash2Icon } from 'lucide-react';\nimport { Fragment, useEffect, useRef } from 'react';\nimport type { ReactNode } from 'react';\nimport { FilterBarChip } from './filter-bar-chip';\nimport { useFilterBarContext } from './filter-bar-context';\nimport { FilterBarInput } from './filter-bar-input';\nimport { countLeaves } from './filter-bar-tree';\nimport type { FilterBarGroup, FilterBarLogic } from './types';\nimport { isFilterBarGroup } from './types';\nimport { useSettleOnLeave } from './use-settle-on-leave';\nimport { Button } from '@/ds/components/Button/Button';\nimport { Txt } from '@/ds/components/Txt';\nimport { cn } from '@/lib/utils';\n\nconst connectorClass =\n 'flex h-control-sm w-14 shrink-0 items-center justify-center rounded-md text-column tracking-wide text-muted-foreground uppercase';\n\nexport type FilterBarLogicToggleProps = {\n groupId: string;\n logic: FilterBarLogic;\n className?: string;\n};\n\n/** `and` / `or` connector in front of a row; every connector of a group shares its logic. */\nexport function FilterBarLogicToggle({ groupId, logic, className }: FilterBarLogicToggleProps) {\n const ctx = useFilterBarContext();\n const next: FilterBarLogic = logic === 'and' ? 'or' : 'and';\n return (\n <button\n type=\"button\"\n data-slot=\"filter-bar-logic\"\n data-logic={logic}\n aria-label={`Joined with ${logic}, switch to ${next}`}\n title={`Switch to ${next}`}\n className={cn(\n connectorClass,\n 'filter-bar-logic cursor-pointer border border-border bg-fill-subtle outline-none',\n 'hover:bg-fill-hover hover:text-foreground focus-visible:bg-fill-hover focus-visible:text-foreground',\n className,\n )}\n onClick={() => ctx.setLogic(groupId, next)}\n >\n {logic}\n </button>\n );\n}\n\n/** Segmented `and | or` control shown in a nested group's header. */\nfunction FilterBarLogicSwitch({ groupId, logic }: { groupId: string; logic: FilterBarLogic }) {\n const ctx = useFilterBarContext();\n return (\n <div\n role=\"radiogroup\"\n aria-label=\"Group logic\"\n className=\"flex h-control-sm items-center gap-0.5 rounded-md border border-border bg-fill-subtle p-0.5\"\n >\n {(['and', 'or'] as const).map(value => (\n <button\n key={value}\n type=\"button\"\n role=\"radio\"\n aria-checked={logic === value}\n aria-label={`Join with ${value}`}\n className={cn(\n 'h-full cursor-pointer rounded-sm px-1.5 text-column tracking-wide uppercase outline-none',\n 'focus-visible:bg-fill-hover',\n logic === value ? 'bg-fill-hover text-foreground' : 'text-muted-foreground hover:text-foreground',\n )}\n onClick={() => logic !== value && ctx.setLogic(groupId, value)}\n >\n {value}\n </button>\n ))}\n </div>\n );\n}\n\nexport type FilterBarGroupEditorProps = {\n group: FilterBarGroup;\n /** Nesting level of `group` (root-level group = 1). */\n depth: number;\n /** Drops this group; rendered as a trailing `Clear all` in the footer. */\n onRemove?: () => void;\n removeLabel?: string;\n className?: string;\n};\n\n/**\n * Recursive rule builder shown in an advanced-filter popover. Rows are laid out as\n * `connector | condition`: the first row reads `where`, the following ones carry the\n * group's `and` / `or` toggle. Nested groups render as bordered cards with their own\n * header (logic switch + remove) and footer. The shared typeahead input renders as the\n * last row of the group it is pointed at.\n */\nexport function FilterBarGroupEditor({\n group,\n depth,\n onRemove,\n removeLabel = 'Remove group',\n className,\n}: FilterBarGroupEditorProps) {\n const ctx = useFilterBarContext();\n const addFilterRef = useRef<HTMLButtonElement>(null);\n const focusAddFilter = useRef(false);\n const targeted = ctx.inputTarget === group.id;\n const canNest = depth < ctx.maxDepth;\n\n // `+ Condition` is hidden while the input is open; focus it once it remounts.\n useEffect(() => {\n if (targeted || !focusAddFilter.current) return;\n focusAddFilter.current = false;\n addFilterRef.current?.focus();\n }, [targeted]);\n\n const rows: ReactNode[] = [];\n const connector = (key: string) =>\n rows.length === 0 ? (\n <span key={`${key}:where`} className={connectorClass}>\n where\n </span>\n ) : (\n <FilterBarLogicToggle key={`${key}:logic`} groupId={group.id} logic={group.logic} />\n );\n for (const node of group.nodes) {\n rows.push(\n <Fragment key={node.id}>\n {connector(node.id)}\n {isFilterBarGroup(node) ? (\n <NestedGroupCard group={node} depth={depth + 1} />\n ) : (\n <FilterBarChip item={node} className=\"w-fit\" />\n )}\n </Fragment>,\n );\n }\n if (ctx.draft && ctx.draft.groupId === group.id) {\n const { id, fieldId, operatorId = '' } = ctx.draft;\n rows.push(\n <Fragment key={id}>\n {connector(id)}\n <FilterBarChip draft item={{ id, fieldId, operatorId, value: '' }} className=\"w-fit\" />\n </Fragment>,\n );\n }\n if (targeted) {\n rows.push(\n <Fragment key=\"input\">\n {connector('input')}\n <FilterBarInput\n groupId={group.id}\n placeholder=\"Add condition\"\n onLeave={() => {\n focusAddFilter.current = true;\n }}\n />\n </Fragment>,\n );\n }\n\n return (\n <div\n data-slot=\"filter-bar-group-editor\"\n data-depth={depth}\n role=\"group\"\n aria-label={`Conditions joined with ${group.logic}`}\n className={cn('flex min-w-0 flex-col', className)}\n >\n {rows.length > 0 && (\n <div className=\"grid grid-cols-[auto_minmax(0,1fr)] items-start gap-x-2 gap-y-1.5 p-2\">{rows}</div>\n )}\n <div\n data-slot=\"filter-bar-editor-actions\"\n className={cn('flex w-full items-center gap-1 p-1', rows.length > 0 && 'border-t border-border')}\n >\n {!targeted && (\n <Button\n ref={addFilterRef}\n variant=\"ghost\"\n size=\"sm\"\n icon={<PlusIcon />}\n onClick={() => ctx.openGroupInput(group.id)}\n >\n Condition\n </Button>\n )}\n <Button\n variant=\"ghost\"\n size=\"sm\"\n icon={<FolderPlusIcon />}\n className=\"text-muted-foreground\"\n tooltip={canNest ? undefined : `Groups can nest ${ctx.maxDepth} levels deep`}\n disabled={!canNest}\n onClick={() => ctx.addGroup(group.id, group.logic === 'and' ? 'or' : 'and')}\n >\n Group\n </Button>\n {onRemove && (\n <Button\n variant=\"ghost\"\n size=\"sm\"\n icon={<Trash2Icon />}\n className=\"ml-auto text-muted-foreground\"\n aria-label={removeLabel}\n onClick={onRemove}\n >\n Clear all\n </Button>\n )}\n </div>\n </div>\n );\n}\n\nfunction NestedGroupCard({ group, depth }: { group: FilterBarGroup; depth: number }) {\n const ctx = useFilterBarContext();\n const rootRef = useRef<HTMLDivElement>(null);\n const leaving = ctx.leaving.has(group.id);\n useSettleOnLeave(group.id, leaving, rootRef);\n const count = countLeaves(group);\n\n return (\n <div\n ref={rootRef}\n data-slot=\"filter-bar-editor-nested\"\n data-leaving={leaving || undefined}\n aria-hidden={leaving || undefined}\n className={cn(\n 'filter-bar-editor-nested w-full overflow-hidden rounded-lg border border-border',\n leaving && 'pointer-events-none',\n )}\n >\n <div className=\"flex items-center gap-2 border-b border-border px-2 py-1\">\n <FolderIcon className=\"size-3.5 text-muted-foreground\" />\n <Txt as=\"span\" variant=\"label\" tone=\"ink\">\n Group\n </Txt>\n <Txt as=\"span\" variant=\"label\" tone=\"muted\">\n · {count} {count === 1 ? 'condition' : 'conditions'}\n </Txt>\n <div className=\"ml-auto flex items-center gap-1\">\n <FilterBarLogicSwitch groupId={group.id} logic={group.logic} />\n <Button\n variant=\"ghost\"\n size=\"icon-sm\"\n tooltip=\"Remove group\"\n disabled={leaving}\n onClick={() => ctx.removeGroup(group.id)}\n >\n <Trash2Icon />\n </Button>\n </div>\n </div>\n <FilterBarGroupEditor group={group} depth={depth} />\n </div>\n );\n}\n","import { BracesIcon, XIcon } from 'lucide-react';\nimport { useRef, useState } from 'react';\nimport type { KeyboardEvent } from 'react';\nimport { chipClass, editableSegmentClass, removeSegmentClass } from './filter-bar-chip';\nimport { FILTER_BAR_SCOPE_ATTR, useFilterBarContext } from './filter-bar-context';\nimport { FilterBarGroupEditor } from './filter-bar-group-editor';\nimport { countLeaves } from './filter-bar-tree';\nimport type { FilterBarGroup } from './types';\nimport { useSettleOnLeave } from './use-settle-on-leave';\nimport { Button } from '@/ds/components/Button/Button';\nimport { Popover, PopoverContent, PopoverTrigger } from '@/ds/components/Popover';\nimport { Txt } from '@/ds/components/Txt';\nimport { cn } from '@/lib/utils';\n\nexport type FilterBarAdvancedChipProps = {\n group: FilterBarGroup;\n className?: string;\n};\n\n/**\n * A root-level group rendered as one \"Advanced filter\" chip. Its popover hosts the\n * recursive rule builder; the chip's remove button drops the whole subtree.\n */\nexport function FilterBarAdvancedChip({ group, className }: FilterBarAdvancedChipProps) {\n const ctx = useFilterBarContext();\n const [initial] = useState(() => !ctx.mounted);\n const rootRef = useRef<HTMLDivElement>(null);\n const triggerRef = useRef<HTMLButtonElement>(null);\n const leaving = ctx.leaving.has(group.id);\n const open = ctx.openGroupId === group.id;\n const count = countLeaves(group);\n // Position in the flattened item list: navigation from the chip continues from its first leaf.\n const firstLeafIndex = ctx.items.findIndex(item => isUnder(group, item.id));\n const index = firstLeafIndex === -1 ? ctx.items.length : firstLeafIndex;\n useSettleOnLeave(group.id, leaving, rootRef);\n\n const handleKeyDown = (event: KeyboardEvent<HTMLDivElement>) => {\n if (leaving) return;\n const segments = Array.from(rootRef.current?.querySelectorAll<HTMLElement>('[data-filter-bar-segment]') ?? []);\n const current = segments.findIndex(el => el === event.target);\n if (current === -1) return;\n switch (event.key) {\n case 'ArrowRight': {\n event.preventDefault();\n const next = segments[current + 1];\n if (next) next.focus();\n else if (!ctx.focusChip(index + count, 1, 'field')) ctx.focusInput();\n return;\n }\n case 'ArrowLeft': {\n event.preventDefault();\n const prev = segments[current - 1];\n if (prev) prev.focus();\n else ctx.focusChip(index - 1, -1, 'remove');\n return;\n }\n case 'Delete':\n case 'Backspace':\n event.preventDefault();\n remove();\n break;\n default:\n }\n };\n\n const remove = () => {\n ctx.removeGroup(group.id);\n ctx.focusAfterRemove(index);\n };\n\n return (\n <Popover open={open} onOpenChange={next => ctx.setOpenGroup(next ? group.id : null)}>\n <div\n ref={rootRef}\n role=\"group\"\n aria-label={`Advanced filter, ${count} ${count === 1 ? 'condition' : 'conditions'}`}\n aria-hidden={leaving || undefined}\n data-slot=\"filter-bar-advanced\"\n data-initial={initial || undefined}\n data-leaving={leaving || undefined}\n className={cn('filter-bar-advanced', chipClass, leaving && 'pointer-events-none', className)}\n onKeyDown={handleKeyDown}\n >\n <PopoverTrigger\n ref={el => {\n triggerRef.current = el;\n ctx.registerSegment(group.id, 'field', leaving ? null : el);\n }}\n render={<button type=\"button\" />}\n data-filter-bar-segment=\"field\"\n className={editableSegmentClass}\n title=\"Edit advanced filter\"\n >\n <BracesIcon aria-hidden />\n <span className=\"truncate\">Advanced filter</span>\n {count > 0 && (\n <Txt as=\"span\" variant=\"column\" tone=\"muted\" aria-hidden>\n {count}\n </Txt>\n )}\n </PopoverTrigger>\n {leaving ? (\n <span aria-hidden className={removeSegmentClass}>\n <XIcon />\n </span>\n ) : (\n <button\n type=\"button\"\n ref={el => ctx.registerSegment(group.id, 'remove', el)}\n data-filter-bar-segment=\"remove\"\n aria-label=\"Remove advanced filter\"\n title=\"Remove advanced filter\"\n className={removeSegmentClass}\n onClick={remove}\n >\n <XIcon />\n </button>\n )}\n </div>\n <PopoverContent\n align=\"start\"\n className=\"w-[min(92vw,44rem)] p-0\"\n {...{ [FILTER_BAR_SCOPE_ATTR]: 'advanced' }}\n finalFocus={triggerRef}\n >\n <div className=\"flex items-center gap-2 border-b border-border px-3 py-2\">\n <BracesIcon className=\"size-3.5 text-muted-foreground\" />\n <Txt as=\"span\" variant=\"label\" tone=\"ink\">\n Advanced filter\n </Txt>\n <Txt as=\"span\" variant=\"column\" tone=\"muted\" className=\"rounded-md bg-fill-subtle px-1.5\">\n {count}\n </Txt>\n <Button\n variant=\"ghost\"\n size=\"icon-sm\"\n className=\"ml-auto\"\n tooltip=\"Close\"\n onClick={() => ctx.setOpenGroup(null)}\n >\n <XIcon />\n </Button>\n </div>\n <FilterBarGroupEditor\n group={group}\n depth={1}\n removeLabel=\"Remove advanced filter\"\n onRemove={() => {\n ctx.setOpenGroup(null);\n remove();\n }}\n />\n </PopoverContent>\n </Popover>\n );\n}\n\nconst isUnder = (group: FilterBarGroup, itemId: string): boolean =>\n group.nodes.some(node => (node.id === itemId ? true : 'kind' in node && isUnder(node, itemId)));\n","import { useFilterBarContext } from './filter-bar-context';\nimport { ClearFiltersButton } from '@/ds/components/ClearFiltersButton/clear-filters-button';\n\n/** Removes every removable filter. Rendered by FilterBar at its trailing edge; hidden while nothing can be removed. */\nexport function FilterBarClear({ label }: { label: string }) {\n const ctx = useFilterBarContext();\n if (!ctx.hasRemovableItems) return null;\n return (\n <ClearFiltersButton\n label={label}\n onClick={event => {\n event.stopPropagation();\n ctx.clear();\n ctx.focusInput();\n }}\n />\n );\n}\n","import { Fragment } from 'react';\nimport type { ReactNode } from 'react';\nimport { FilterBarAdvancedChip } from './filter-bar-advanced-chip';\nimport { FilterBarChip } from './filter-bar-chip';\nimport { FilterBarClear } from './filter-bar-clear';\nimport { FILTER_BAR_SCOPE_ATTR, FilterBarProvider, useFilterBarContext } from './filter-bar-context';\nimport { FilterBarInput } from './filter-bar-input';\nimport { FilterBarTimeRange } from './filter-bar-time-range';\nimport { isFilterBarGroup } from './types';\nimport type { FilterBarExpression, FilterBarField, FilterBarItem, FilterBarOperator } from './types';\nimport { VisuallyHidden } from '@/ds/primitives/visually-hidden';\nimport { cn } from '@/lib/utils';\n\ntype FilterBarValueProps =\n | {\n /** Flat list of filters, implicitly joined with `and`. Advanced filters are never offered. */\n value: FilterBarItem[];\n onValueChange: (items: FilterBarItem[]) => void;\n }\n | {\n /**\n * Tree of filters and groups. Root nodes are joined with `and`; each root group renders\n * as one \"Advanced filter\" chip whose popover edits the nested `and` / `or` logic.\n */\n value: FilterBarExpression;\n onValueChange: (expression: FilterBarExpression) => void;\n };\n\nexport type FilterBarProps = FilterBarValueProps & {\n fields: FilterBarField[];\n operators: FilterBarOperator[];\n /**\n * Id given to a newly added item. Defaults to a random id. Consumers that rebuild `value` from\n * their own store (URL, query params…) should return the id they will rebuild it with, so the\n * draft chip and the committed chip are the same element.\n */\n createItemId?: (fieldId: string) => string;\n /** How deep advanced-filter groups may nest (root-level group = 1). Defaults to 3. */\n maxDepth?: number;\n 'aria-label'?: string;\n /**\n * Text shown in a value list when the field's `suggestions` resolver rejects, for example\n * to explain a server limit. Return `undefined` to keep the default \"Couldn't load values.\".\n */\n describeSuggestionsError?: (error: unknown) => string | undefined;\n /** Accessible label of the trailing \"remove every filter\" button. */\n clearLabel?: string;\n className?: string;\n children: ReactNode;\n};\n\nfunction FilterBarSurface({\n className,\n clearLabel,\n children,\n}: {\n className?: string;\n clearLabel: string;\n children: ReactNode;\n}) {\n const ctx = useFilterBarContext();\n return (\n <div\n role=\"group\"\n aria-label={ctx.ariaLabel}\n data-slot=\"filter-bar\"\n {...{ [FILTER_BAR_SCOPE_ATTR]: 'bar' }}\n className={cn(\n // No chrome of its own: chips and the typeahead input sit directly on the parent surface.\n // Layout: chips, input, then Clear right beside the input — all in one wrapping row so\n // Clear never drifts to the far edge of a wide container.\n 'flex w-full flex-wrap items-center gap-1.5',\n className,\n )}\n >\n {children}\n <span className=\"flex shrink-0 items-center empty:hidden\">\n <FilterBarClear label={clearLabel} />\n </span>\n <VisuallyHidden aria-live=\"polite\">{ctx.announcement}</VisuallyHidden>\n </div>\n );\n}\n\n/**\n * Braintrust-style filter bar: `field → operator → value` filters built from a\n * single typeahead input, rendered as inline editable chips. Domain-agnostic —\n * fields, operators and values are plain strings supplied by the consumer.\n *\n * Pass a `FilterBarExpression` as `value` to enable Linear-style advanced filters:\n * the input offers \"Advanced filter…\", which adds one chip whose popover hosts a\n * recursive rule builder (`and` / `or` connectors, nested groups). The bar itself\n * stays flat. A flat `FilterBarItem[]` stays flat.\n *\n * @example\n * <FilterBar value={items} onValueChange={setItems} fields={fields} operators={DEFAULT_FILTER_OPERATORS}>\n * <FilterBar.Chips />\n * <FilterBar.Input />\n * </FilterBar>\n */\nexport function FilterBar({\n fields,\n operators,\n value,\n onValueChange,\n createItemId,\n maxDepth,\n 'aria-label': ariaLabel = 'Filters',\n describeSuggestionsError,\n clearLabel = 'Clear filters',\n className,\n children,\n}: FilterBarProps) {\n return (\n <FilterBarProvider\n fields={fields}\n operators={operators}\n value={value}\n onValueChange={onValueChange}\n createItemId={createItemId}\n maxDepth={maxDepth}\n ariaLabel={ariaLabel}\n describeSuggestionsError={describeSuggestionsError}\n >\n <FilterBarSurface className={className} clearLabel={clearLabel}>\n {children}\n </FilterBarSurface>\n </FilterBarProvider>\n );\n}\n\n/**\n * Default layout: one editable chip per root item, one \"Advanced filter\" chip per root\n * group, in order, then the chip of the filter being built in the bar's input (which\n * becomes the last item's chip once committed).\n */\nexport function FilterBarChips({ renderChip = defaultRenderChip }: FilterBarChipsProps) {\n const ctx = useFilterBarContext();\n // One keyed array: the draft chip and the item it becomes share a key, so React\n // keeps the element across the commit instead of mounting a new chip.\n const chips: ReactNode[] = [];\n for (const node of ctx.expression.nodes) {\n const chip = isFilterBarGroup(node) ? <FilterBarAdvancedChip group={node} /> : renderChip(node);\n if (chip !== null) chips.push(<Fragment key={node.id}>{chip}</Fragment>);\n }\n if (ctx.draft && !ctx.draft.groupId) {\n // `FilterBarChip` needs a full item; the draft's missing parts are blank until picked.\n const { id, fieldId, operatorId = '' } = ctx.draft;\n chips.push(\n <Fragment key={id}>\n <FilterBarChip draft item={{ id, fieldId, operatorId, value: '' }} />\n </Fragment>,\n );\n }\n return <>{chips}</>;\n}\n\nexport type FilterBarChipsProps = {\n /**\n * Chip for an item; return `null` to render none (e.g. an item only held in the\n * value for scoping). Defaults to a plain editable `FilterBar.Chip`.\n */\n renderChip?: (item: FilterBarItem) => ReactNode;\n};\n\nconst defaultRenderChip = (item: FilterBarItem) => <FilterBarChip item={item} />;\n\nFilterBar.Chips = FilterBarChips;\nFilterBar.Chip = FilterBarChip;\nFilterBar.AdvancedChip = FilterBarAdvancedChip;\nFilterBar.Input = FilterBarInput;\nFilterBar.TimeRange = FilterBarTimeRange;\n","import type { FilterBarOperator } from './types';\n\n/** Opt-in starter set. Pure data: the component attaches no semantics to ids. */\nexport const DEFAULT_FILTER_OPERATORS: FilterBarOperator[] = [\n { id: 'is', label: 'is', widensTo: 'in' },\n { id: 'is-not', label: 'is not' },\n { id: 'contains', label: 'contains' },\n { id: 'not-contains', label: 'does not contain' },\n { id: 'starts-with', label: 'starts with' },\n { id: 'gt', label: '>' },\n { id: 'lt', label: '<' },\n { id: 'gte', label: '>=' },\n { id: 'lte', label: '<=' },\n { id: 'is-empty', label: 'is empty', arity: 'none' },\n { id: 'is-not-empty', label: 'is not empty', arity: 'none' },\n { id: 'in', label: 'in', arity: 'many' },\n];\n"],"mappings":"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"}
@@ -9,3 +9,58 @@
9
9
  outline: 2px solid var(--knowledge-color);
10
10
  outline-offset: 5px;
11
11
  }
12
+
13
+ /* The focused page: a heavier border and a soft halo, so it reads as the centre of the graph. */
14
+ .knowledge-circle[data-selected='true'] {
15
+ border-width: 4px;
16
+ box-shadow: 0 0 22px 4px color-mix(in srgb, var(--knowledge-color) 45%, transparent);
17
+ }
18
+
19
+ /* A refocus: pages in both views glide and resize to their new place, new ones fade in, and ones that
20
+ leave are faded out (the graph keeps them a moment). Under reduced motion every one of these is off. */
21
+ .knowledge-graph {
22
+ /* Keep in step with KNOWLEDGE_GRAPH_TRANSITION_MS in lib/useLeavingNodes.ts. */
23
+ --knowledge-graph-transition: 700ms cubic-bezier(0.65, 0, 0.35, 1);
24
+ }
25
+
26
+ .knowledge-graph .react-flow__node {
27
+ transition:
28
+ transform var(--knowledge-graph-transition),
29
+ width var(--knowledge-graph-transition),
30
+ height var(--knowledge-graph-transition),
31
+ opacity var(--knowledge-graph-transition);
32
+ animation: knowledge-node-in var(--knowledge-graph-transition) both;
33
+ }
34
+
35
+ @keyframes knowledge-node-in {
36
+ from {
37
+ opacity: 0;
38
+ }
39
+ }
40
+
41
+ @media (prefers-reduced-motion: reduce) {
42
+ .knowledge-graph .react-flow__node {
43
+ transition: none;
44
+ animation: none;
45
+ }
46
+ }
47
+
48
+ /* With a page hovered or selected, everything but its neighbourhood fades. It fades the node's content, not
49
+ the node: the node's own opacity belongs to the view change, and a short fade keeps pointing responsive. */
50
+ .knowledge-graph .react-flow__node > *,
51
+ .knowledge-graph .react-flow__edge {
52
+ transition: opacity 150ms ease-out;
53
+ }
54
+
55
+ .knowledge-graph[data-emphasis] .react-flow__node:not(.knowledge-neighbour) > * {
56
+ opacity: 0.35;
57
+ }
58
+
59
+ .knowledge-graph[data-emphasis] .react-flow__edge:not(.knowledge-neighbour) {
60
+ opacity: 0.2;
61
+ }
62
+
63
+ /* A hovered dot's tooltip sits above every other circle. */
64
+ .knowledge-graph .react-flow__node:hover {
65
+ z-index: 1000 !important;
66
+ }
@@ -329,11 +329,15 @@ function useSettledWords(words, streaming) {
329
329
  * halfway through reading would be both a lie and a screenful of animations at
330
330
  * once.
331
331
  */
332
- var MarkdownRenderer = memo(function MarkdownRenderer({ children, className, externalLinkTarget = "tab", streaming = false, tableActions = false }) {
332
+ var MarkdownRenderer = memo(function MarkdownRenderer({ children, className, externalLinkTarget = "tab", streaming = false, tableActions = false, remarkPlugins: extraRemarkPlugins, components: extraComponents }) {
333
333
  const shown = decodeEscapedNewlines(children);
334
334
  const blocks = useMemo(() => splitBlocks(shown), [shown]);
335
335
  const last = blocks.length - 1;
336
- const components = (tableActions ? TABLE_COMPONENTS : DEFAULT_COMPONENTS)[externalLinkTarget];
336
+ const baseComponents = (tableActions ? TABLE_COMPONENTS : DEFAULT_COMPONENTS)[externalLinkTarget];
337
+ const components = useMemo(() => extraComponents ? {
338
+ ...baseComponents,
339
+ ...extraComponents
340
+ } : baseComponents, [baseComponents, extraComponents]);
337
341
  const spans = wordSpans(blocks);
338
342
  const settled = useSettledWords(spans.at(-1)?.end ?? 0, streaming);
339
343
  const settledWords = (span) => !span || settled >= span.end ? void 0 : Math.max(0, settled - span.start);
@@ -346,15 +350,24 @@ var MarkdownRenderer = memo(function MarkdownRenderer({ children, className, ext
346
350
  settledWords: settledWords(spans[index]),
347
351
  components,
348
352
  streaming,
349
- tableActions
353
+ tableActions,
354
+ extraRemarkPlugins
350
355
  }, index))
351
356
  });
352
357
  });
353
358
  /** Keyed by position at the call site: a content key remounts on every character. */
354
- var MarkdownBlock = memo(function MarkdownBlock({ components, content, settledWords, streaming, tableActions }) {
359
+ var MarkdownBlock = memo(function MarkdownBlock({ components, content, settledWords, streaming, tableActions, extraRemarkPlugins }) {
360
+ const remarkPlugins = useMemo(() => {
361
+ const builtIn = tableActions && !streaming ? COPYABLE_REMARK_PLUGINS : REMARK_PLUGINS;
362
+ return extraRemarkPlugins ? [...builtIn, ...extraRemarkPlugins] : builtIn;
363
+ }, [
364
+ tableActions,
365
+ streaming,
366
+ extraRemarkPlugins
367
+ ]);
355
368
  const rehypePlugins = useMemo(() => settledWords === void 0 ? SETTLED : [rehypeArriving(settledWords)], [settledWords]);
356
369
  return /* @__PURE__ */ jsx(Markdown, {
357
- remarkPlugins: tableActions && !streaming ? COPYABLE_REMARK_PLUGINS : REMARK_PLUGINS,
370
+ remarkPlugins,
358
371
  rehypePlugins,
359
372
  components,
360
373
  children: content
@@ -465,4 +478,4 @@ var TABLE_COMPONENTS = {
465
478
  };
466
479
  export { MarkdownRenderer as t };
467
480
 
468
- //# sourceMappingURL=MarkdownRenderer-2GOXQJEv.js.map
481
+ //# sourceMappingURL=MarkdownRenderer-CI30RqdB.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MarkdownRenderer-CI30RqdB.js","names":[],"sources":["../src/ds/components/MarkdownRenderer/arriving.ts","../src/ds/components/MarkdownRenderer/blocks.ts","../src/ds/components/MarkdownRenderer/table-csv.ts","../src/ds/components/MarkdownRenderer/markdown-table.tsx","../src/ds/components/MarkdownRenderer/table-markdown.ts","../src/ds/components/MarkdownRenderer/use-settled.ts","../src/ds/components/MarkdownRenderer/markdown-renderer.tsx"],"sourcesContent":["import type { ExtraProps } from 'react-markdown';\n\nimport { ARRIVING_CLASS } from '@/ds/tokens';\n\nimport '@/ds/components/Arrival/arrival.css';\n\ntype MarkdownElement = NonNullable<ExtraProps['node']>;\ntype MarkdownChild = MarkdownElement['children'][number];\n\n/** Fades whole: a fence renders through `CodeBlock`, and inline code carries a background. */\nconst UNBROKEN = new Set(['pre', 'code']);\n\nconst wrap = (value: string, arriving: boolean): MarkdownChild => ({\n type: 'element',\n tagName: 'span',\n properties: arriving ? { className: [ARRIVING_CLASS] } : {},\n children: [{ type: 'text', value }],\n});\n\nfunction markArriving(node: MarkdownElement): void {\n const classes = node.properties.className;\n\n node.properties.className = Array.isArray(classes) ? [...classes, ARRIVING_CLASS] : [ARRIVING_CLASS];\n}\n\nfunction rebuild(nodes: MarkdownChild[], arriving: () => boolean): MarkdownChild[] {\n const out: MarkdownChild[] = [];\n\n for (const node of nodes) {\n if (node.type === 'text') {\n for (const piece of node.value.match(/\\S+|\\s+/g) ?? []) {\n if (/\\S/.test(piece)) out.push(wrap(piece, arriving()));\n else out.push({ type: 'text', value: piece });\n }\n\n continue;\n }\n\n out.push(node);\n\n if (node.type !== 'element') continue;\n\n if (!UNBROKEN.has(node.tagName)) node.children = rebuild(node.children, arriving);\n else if (arriving()) markArriving(node);\n }\n\n return out;\n}\n\n/**\n * Gives every word of a block an element of its own, and the entrance class to\n * those past the first `settled` — the words that were not on screen yet when\n * the reader joined this reply.\n *\n * Every word, not just the arriving ones: react-markdown parses afresh on each\n * landing and React matches the children it already mounted by position, so a\n * wrapper that came and went would land where a bare text node used to be and\n * remount half the paragraph, replaying entrances that had long finished.\n * Wrapping the lot keeps every position fixed — a new word only ever appends —\n * and a word never gains the class it did not mount with, so nothing replays.\n */\nexport function rehypeArriving(settled: number) {\n return function attach() {\n return (tree: { children: MarkdownChild[] }) => {\n let word = 0;\n\n tree.children = rebuild(tree.children, () => word++ >= settled);\n };\n };\n}\n","const FENCE_OPEN = /^ {0,3}(`{3,}|~{3,})/;\nconst FENCE_CLOSE = /^ {0,3}(`{3,}|~{3,})[ \\t]*$/;\nconst LIST_ITEM = /^ {0,3}(?:[-*+]|\\d{1,9}[.)])(?:[ \\t]|$)/;\nconst INDENTED = /^(?:\\t| {2,})/;\nconst DEFINITION = /^ {0,3}\\[[^\\]]+\\]:/;\n\nfunction fenceOpenedBy(line: string): string | undefined {\n return FENCE_OPEN.exec(line)?.[1];\n}\n\n// Both are runs of one character, so `startsWith` is \"same marker, at least as long\".\nfunction closesFence(line: string, marker: string): boolean {\n return FENCE_CLOSE.exec(line)?.[1]?.startsWith(marker) ?? false;\n}\n\nfunction startsBlock(line: string, inList: boolean): boolean {\n if (INDENTED.test(line)) return false;\n\n return !(inList && LIST_ITEM.test(line));\n}\n\n/**\n * Cuts markdown into top-level blocks so a growing reply re-parses its last\n * block instead of all of them. Rejoining the result returns the input, and\n * every block renders as it would have inside the whole.\n *\n * Each rule only ever merges: over-merging costs a re-parse, while cutting a\n * construct in two changes what it renders as. Link reference and footnote\n * definitions resolve across blank lines, which no line-level rule can see, so\n * reaching one outside a fence abandons the split for the whole text.\n */\nexport function splitBlocks(markdown: string): string[] {\n const lines = markdown.split('\\n');\n const starts = [0];\n let fence: string | undefined;\n let started = false;\n let broken = false;\n let inList = false;\n\n for (const [index, line] of lines.entries()) {\n if (fence) {\n if (closesFence(line, fence)) fence = undefined;\n continue;\n }\n\n if (line.trim() === '') {\n broken = started;\n continue;\n }\n\n if (DEFINITION.test(line)) return [markdown];\n\n if (broken && startsBlock(line, inList)) {\n starts.push(index);\n started = false;\n }\n\n if (!started) inList = LIST_ITEM.test(line);\n\n started = true;\n broken = false;\n fence = fenceOpenedBy(line);\n }\n\n return starts.map((start, position) => {\n const end = starts[position + 1];\n const block = lines.slice(start, end ?? lines.length).join('\\n');\n\n return end === undefined ? block : `${block}\\n`;\n });\n}\n","function spreadsheetCell(value: string): string {\n // Quoting alone does not stop spreadsheet apps from evaluating formulas.\n const numeric = /^[+-]?(?:\\d+(?:\\.\\d*)?|\\.\\d+)(?:e[+-]?\\d+)?$/i.test(value.trim());\n const formula = /^[\\s\\uFEFF]*[=+\\-@=+-@]/u.test(value);\n const controlPrefix = /^[\\t\\r\\n]/.test(value);\n const safe = controlPrefix || (formula && !numeric) ? `'${value}` : value;\n return `\"${safe.replaceAll('\"', '\"\"')}\"`;\n}\n\nexport function tableToCsv(rows: string[][]): string {\n return rows.map(row => row.map(spreadsheetCell).join(',')).join('\\r\\n');\n}\n\nexport function downloadTableCsv(csv: string): void {\n const blob = new Blob(['\\uFEFF', csv], { type: 'text/csv;charset=utf-8' });\n const url = URL.createObjectURL(blob);\n const anchor = document.createElement('a');\n anchor.href = url;\n anchor.download = 'table.csv';\n document.body.appendChild(anchor);\n anchor.click();\n anchor.remove();\n URL.revokeObjectURL(url);\n}\n","import { CheckIcon, ChevronDownIcon, CopyIcon, DownloadIcon } from 'lucide-react';\nimport type { ComponentProps } from 'react';\nimport type { ExtraProps } from 'react-markdown';\nimport { downloadTableCsv } from './table-csv';\nimport { Button } from '@/ds/components/Button';\nimport { ButtonsGroup } from '@/ds/components/ButtonsGroup';\nimport { DropdownMenu } from '@/ds/components/DropdownMenu';\nimport { useCopyToClipboard } from '@/hooks/use-copy-to-clipboard';\n\nexport function MarkdownTable({ node, children }: ComponentProps<'table'> & ExtraProps) {\n const markdown = node?.properties.tableMarkdown;\n const csv = node?.properties.tableCsv;\n const { isCopied, copyToClipboard } = useCopyToClipboard({ copyMessage: 'Copied table markdown' });\n\n return (\n <div className=\"my-3 w-fit max-w-full min-w-0\">\n <div className=\"flex justify-end\">\n <ButtonsGroup size=\"sm\" aria-label=\"Table actions\">\n <Button\n type=\"button\"\n variant=\"ghost\"\n disabled={typeof markdown !== 'string'}\n onClick={() => {\n if (typeof markdown === 'string') copyToClipboard(markdown);\n }}\n aria-label=\"Copy table as markdown\"\n >\n {isCopied ? <CheckIcon /> : <CopyIcon />}\n {isCopied ? 'Copied!' : 'Copy table as markdown'}\n </Button>\n <DropdownMenu>\n <DropdownMenu.Trigger\n disabled={typeof csv !== 'string'}\n render={\n <Button type=\"button\" size=\"icon-sm\" variant=\"ghost\" aria-label=\"More table options\">\n <ChevronDownIcon />\n </Button>\n }\n />\n <DropdownMenu.Content align=\"end\" size=\"sm\" className=\"w-max min-w-0\">\n <DropdownMenu.Item\n size=\"sm\"\n onClick={() => {\n if (typeof csv === 'string') downloadTableCsv(csv);\n }}\n >\n <DownloadIcon />\n Download CSV\n </DropdownMenu.Item>\n </DropdownMenu.Content>\n </DropdownMenu>\n </ButtonsGroup>\n </div>\n <div className=\"max-w-full overflow-x-auto\">\n <table className=\"table min-w-full\">{children}</table>\n </div>\n </div>\n );\n}\n","import type { Definition, FootnoteDefinition, Nodes, Root, Table } from 'mdast';\nimport { gfmToMarkdown } from 'mdast-util-gfm';\nimport { toMarkdown } from 'mdast-util-to-markdown';\nimport { tableToCsv } from './table-csv';\n\nfunction cellText(node: Nodes): string {\n if (node.type === 'footnoteReference') return `[^${node.label ?? node.identifier}]`;\n if ('value' in node) return node.value;\n if (node.type === 'image' || node.type === 'imageReference') return node.alt ?? '';\n return 'children' in node ? node.children.map(cellText).join('') : '';\n}\n\nfunction walk(node: Nodes, visit: (node: Nodes) => void): void {\n visit(node);\n if ('children' in node) node.children.forEach(child => walk(child, visit));\n}\n\nconst SERIALIZE_OPTIONS = { extensions: [gfmToMarkdown()] };\n\n/** Capture table exports before rehype replaces text with animation spans. */\nexport function remarkTableMarkdown() {\n return (tree: Root, file: { value: unknown }) => {\n const source = String(file.value);\n const definitions = new Map<string, Definition | FootnoteDefinition>();\n const tables: Table[] = [];\n walk(tree, node => {\n if (node.type === 'definition' || node.type === 'footnoteDefinition') {\n const key = `${node.type}:${node.identifier}`;\n if (!definitions.has(key)) definitions.set(key, node);\n }\n if (node.type === 'table') tables.push(node);\n });\n\n const lines = source.split(/\\r\\n|\\r|\\n/);\n for (const table of tables) {\n const header = table.children[0];\n if (!header?.position) continue;\n const rows = table.children.map(row => {\n const start = row.position?.start.offset;\n const end = row.position?.end.offset;\n return start === undefined || end === undefined ? undefined : source.slice(start, end);\n });\n // Only offer exports when the parser supplied the original row locations.\n if (!rows.every(row => row !== undefined)) continue;\n // Row positions exclude list/blockquote prefixes. The delimiter has no AST node.\n const delimiter = lines[header.position.start.line]?.replace(/^[\\t >]*/, '');\n if (delimiter === undefined) continue;\n const markdown = [rows[0], delimiter, ...rows.slice(1)];\n const used = new Set<string>();\n const collectReference = (node: Nodes) => {\n if (node.type === 'linkReference' || node.type === 'imageReference') {\n used.add(`definition:${node.identifier}`);\n } else if (node.type === 'footnoteReference') {\n used.add(`footnoteDefinition:${node.identifier}`);\n }\n };\n walk(table, collectReference);\n // Visiting appended definitions also collects links/footnotes they depend on.\n // The set prevents duplicates and cycles, including self-referencing footnotes.\n for (const key of used) {\n const definition = definitions.get(key);\n if (!definition) continue;\n markdown.push('', toMarkdown(definition, SERIALIZE_OPTIONS).trimEnd());\n walk(definition, collectReference);\n }\n const cells = table.children.map(row =>\n Array.from({ length: header.children.length }, (_, index) => {\n const cell = row.children[index];\n return cell ? cellText(cell) : '';\n }),\n );\n table.data = {\n ...table.data,\n hProperties: {\n ...table.data?.hProperties,\n tableMarkdown: markdown.join('\\n'),\n tableCsv: tableToCsv(cells),\n },\n };\n }\n };\n}\n","import { useEffect, useRef, useState } from 'react';\n\nimport { useWatched } from '@/ds/components/Arrival';\nimport { ARRIVING_MS } from '@/ds/tokens';\n\ninterface Landing {\n words: number;\n at: number;\n}\n\n/**\n * How many of a reply's words have been on screen long enough that their entrance is over.\n *\n * The entrance plays on whatever mounts carrying the class, so it replays every time a\n * word's element is rebuilt — and markdown rebuilds a growing tail constantly: a `-`\n * turns a paragraph into a list item, a closing `**` splits it around a `<strong>`, the\n * stream ends and the mend comes off. Each of those swaps the element a settled word\n * lives in, which is what makes a word already read fade in again.\n *\n * Ageing them out is the whole answer: a word carries the class only while it is new,\n * so however often the tail is rebuilt, only what is genuinely arriving animates.\n *\n * What counts as new at mount is not this hook's call. A reply the reader was handed\n * is already there, and a block that mounts complete — a card's output, an expanded\n * body — enters with its container. Only a passage born streaming under the reader's\n * eyes is new from its first word: the reveal often lands several words in its first\n * commit, and they enter like every word after them.\n */\nexport function useSettledWords(words: number, streaming: boolean): number {\n const watched = useWatched();\n const [settled, setSettled] = useState(() => (watched && streaming ? 0 : words));\n const landings = useRef<Landing[]>([]);\n const recorded = useRef(settled);\n\n useEffect(() => {\n if (recorded.current !== words) {\n landings.current.push({ words, at: performance.now() });\n recorded.current = words;\n }\n\n const waiting = landings.current[0];\n if (!waiting) return;\n\n const timer = setTimeout(\n () => {\n landings.current.shift();\n setSettled(waiting.words);\n },\n Math.max(0, waiting.at + ARRIVING_MS - performance.now()),\n );\n\n return () => clearTimeout(timer);\n }, [settled, words]);\n\n // A shorter reply replacing the one on screen settles at once: nothing of it is new.\n return Math.min(settled, words);\n}\n","import { memo, useMemo } from 'react';\nimport type { MouseEvent, MouseEventHandler, ReactNode } from 'react';\nimport Markdown from 'react-markdown';\nimport type { Components, ExtraProps, Options } from 'react-markdown';\nimport remarkGfm from 'remark-gfm';\nimport remend from 'remend';\n\nimport { rehypeArriving } from './arriving';\nimport { splitBlocks } from './blocks';\nimport { MarkdownTable } from './markdown-table';\nimport { remarkTableMarkdown } from './table-markdown';\nimport { useSettledWords } from './use-settled';\nimport { CodeBlock } from '@/ds/components/CodeBlock';\nimport { cn } from '@/lib/utils';\n\nimport './markdown-renderer.css';\n\nexport type MarkdownExternalLinkTarget = 'tab' | 'window';\n\ntype RemarkPlugins = NonNullable<Options['remarkPlugins']>;\n\nexport interface MarkdownRendererProps {\n children: string;\n className?: string;\n externalLinkTarget?: MarkdownExternalLinkTarget;\n /** The text is a prefix of one still being written: close the markers the stream has not reached. */\n streaming?: boolean;\n /** Opt in to table copy/download controls; disabled while this text is streaming. */\n tableActions?: boolean;\n /** Remark plugins run after the built-in ones, e.g. to turn a syntax of the host's into elements. Keep it stable. */\n remarkPlugins?: RemarkPlugins;\n /** Element overrides merged over the built-in ones. Keep it stable: a new object re-renders every block. */\n components?: Components;\n}\n\n/**\n * Renders a markdown string. Agent output can carry attacker-influenced text\n * (file contents, tool output, web pages): react-markdown escapes raw HTML and\n * drops dangerous link schemes, so nothing here reaches the DOM as markup.\n *\n * react-markdown re-parses on every render, and a streaming reply re-renders\n * its whole transcript on every delta. Memoizing spares the settled messages;\n * rendering block by block — streaming or not — spares every block of the live\n * one but the last, and lets a reply settle without remounting what is already\n * on screen.\n *\n * The text is drawn as given: pacing a stream is `useRevealedText`, and belongs to\n * whoever owns the whole of what is being laid down — a reply is prose, tool rows\n * and cards, and they have to arrive in the order they were written. Only what\n * lands after the reader joined plays an entrance, and only while it is still new:\n * a reply opened part-written is already there, and fading in what someone is\n * halfway through reading would be both a lie and a screenful of animations at\n * once.\n */\nexport const MarkdownRenderer = memo(function MarkdownRenderer({\n children,\n className,\n externalLinkTarget = 'tab',\n streaming = false,\n tableActions = false,\n remarkPlugins: extraRemarkPlugins,\n components: extraComponents,\n}: MarkdownRendererProps) {\n const shown = decodeEscapedNewlines(children);\n const blocks = useMemo(() => splitBlocks(shown), [shown]);\n const last = blocks.length - 1;\n const baseComponents = (tableActions ? TABLE_COMPONENTS : DEFAULT_COMPONENTS)[externalLinkTarget];\n const components = useMemo(\n () => (extraComponents ? { ...baseComponents, ...extraComponents } : baseComponents),\n [baseComponents, extraComponents],\n );\n\n const spans = wordSpans(blocks);\n const settled = useSettledWords(spans.at(-1)?.end ?? 0, streaming);\n\n // A block whose words have all finished their entrance has nothing left to play,\n // which is what `undefined` says: leave it as plain text, no spans at all.\n const settledWords = (span: WordSpan | undefined): number | undefined =>\n !span || settled >= span.end ? undefined : Math.max(0, settled - span.start);\n\n const tail = blocks[last] ?? '';\n const mended = useMemo(() => (streaming ? remend(tail, REMEND_OPTIONS) : tail), [streaming, tail]);\n\n return (\n <div className={cn('mastra-markdown', className)}>\n {blocks.map((block, index) => (\n <MarkdownBlock\n key={index}\n content={index === last ? mended : block}\n settledWords={settledWords(spans[index])}\n components={components}\n streaming={streaming}\n tableActions={tableActions}\n extraRemarkPlugins={extraRemarkPlugins}\n />\n ))}\n </div>\n );\n});\n\n/** Keyed by position at the call site: a content key remounts on every character. */\nconst MarkdownBlock = memo(function MarkdownBlock({\n components,\n content,\n settledWords,\n streaming,\n tableActions,\n extraRemarkPlugins,\n}: {\n components: Components;\n content: string;\n settledWords?: number;\n streaming: boolean;\n tableActions: boolean;\n extraRemarkPlugins?: RemarkPlugins;\n}) {\n const remarkPlugins = useMemo(() => {\n const builtIn = tableActions && !streaming ? COPYABLE_REMARK_PLUGINS : REMARK_PLUGINS;\n return extraRemarkPlugins ? [...builtIn, ...extraRemarkPlugins] : builtIn;\n }, [tableActions, streaming, extraRemarkPlugins]);\n const rehypePlugins = useMemo(\n () => (settledWords === undefined ? SETTLED : [rehypeArriving(settledWords)]),\n [settledWords],\n );\n\n return (\n <Markdown remarkPlugins={remarkPlugins} rehypePlugins={rehypePlugins} components={components}>\n {content}\n </Markdown>\n );\n});\n\nconst SETTLED: Options['rehypePlugins'] = [];\n\ninterface WordSpan {\n start: number;\n end: number;\n}\n\n/**\n * Where each block's words fall in the reply's own count, so one settled count covers\n * them all. Counting the source counts its markers too, so the boundary only ever errs\n * towards leaving a word unanimated.\n */\nfunction wordSpans(blocks: string[]): WordSpan[] {\n let read = 0;\n\n return blocks.map(block => {\n const span = { start: read, end: read + countWords(block) };\n read = span.end;\n\n return span;\n });\n}\n\nfunction countWords(text: string): number {\n return text.match(/\\S+/g)?.length ?? 0;\n}\n\n// Agent networks emit their text with literal `\\n`. Only unescape when the text\n// has no real newline, otherwise a `\"a\\nb\"` inside a code fence gets shredded.\nfunction decodeEscapedNewlines(text: string): string {\n return text.includes('\\n') ? text : text.replace(/\\\\n/g, '\\n');\n}\n\ntype MarkdownNode = NonNullable<ExtraProps['node']>;\n\nfunction languageOf(node: MarkdownNode): string | undefined {\n const classNames = node.properties.className;\n if (!Array.isArray(classNames)) return undefined;\n\n const language = classNames.find(entry => typeof entry === 'string' && entry.startsWith('language-'));\n return typeof language === 'string' ? language.slice('language-'.length) : undefined;\n}\n\nfunction fencedCode(node: MarkdownNode | undefined): { code: string; language?: string } | undefined {\n const child = node?.children.find(entry => entry.type === 'element' && entry.tagName === 'code');\n if (child?.type !== 'element') return undefined;\n\n const code = child.children.map(entry => (entry.type === 'text' ? entry.value : '')).join('');\n return { code: code.replace(/\\n$/, ''), language: languageOf(child) };\n}\n\nfunction MarkdownCodeBlock({\n node,\n children,\n className,\n}: {\n node?: MarkdownNode;\n children?: ReactNode;\n className?: string;\n}) {\n const fenced = fencedCode(node);\n if (!fenced) return <pre className={className}>{children}</pre>;\n\n return (\n <CodeBlock\n code={fenced.code}\n lang={fenced.language}\n overflow=\"scroll\"\n className={cn('my-3 bg-sidebar', className)}\n copyMessage=\"Copied code to clipboard\"\n />\n );\n}\n\nconst POPUP_WINDOW_FEATURES = 'popup=yes,width=720,height=800,resizable=yes,scrollbars=yes';\n\nfunction isPlainLeftClick(event: MouseEvent): boolean {\n return event.button === 0 && !event.metaKey && !event.ctrlKey && !event.shiftKey && !event.altKey;\n}\n\nfunction markdownLink(externalLinkTarget: MarkdownExternalLinkTarget): NonNullable<Components['a']> {\n return function MarkdownLink({ href, title, children }) {\n const isExternal = /^https?:\\/\\//i.test(href ?? '');\n\n const openInPopup: MouseEventHandler<HTMLAnchorElement> = event => {\n if (!isExternal || externalLinkTarget !== 'window' || !isPlainLeftClick(event)) return;\n\n const popup = window.open(href, '_blank', POPUP_WINDOW_FEATURES);\n if (!popup) return;\n\n popup.opener = null;\n event.preventDefault();\n };\n\n return (\n <a\n href={href}\n title={title}\n onClick={openInPopup}\n target={isExternal ? '_blank' : undefined}\n rel={isExternal ? 'noopener noreferrer' : undefined}\n >\n {children}\n </a>\n );\n };\n}\n\nconst REMARK_PLUGINS = [remarkGfm];\nconst COPYABLE_REMARK_PLUGINS = [remarkGfm, remarkTableMarkdown];\n\n// Links stay text until their URL lands: remend's placeholder href would render\n// a live anchor to nowhere. No math is rendered here, so pairing `$$` would only\n// turn one literal into another.\nconst REMEND_OPTIONS = { katex: false, linkMode: 'text-only' } as const;\n\n// Elements are listed one by one: react-markdown also passes its `node`, which\n// React would forward to the DOM as a stray attribute. Everything else is\n// styled from markdown-renderer.css.\nconst COMPONENTS: Components = {\n pre: MarkdownCodeBlock,\n a: markdownLink('tab'),\n};\n\nconst WINDOW_COMPONENTS: Components = {\n ...COMPONENTS,\n a: markdownLink('window'),\n};\n\nconst DEFAULT_COMPONENTS = { tab: COMPONENTS, window: WINDOW_COMPONENTS };\nconst TABLE_COMPONENTS = {\n tab: { ...COMPONENTS, table: MarkdownTable },\n window: { ...WINDOW_COMPONENTS, table: MarkdownTable },\n};\n"],"mappings":"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"}
@@ -333,11 +333,15 @@ function useSettledWords(words, streaming) {
333
333
  * halfway through reading would be both a lie and a screenful of animations at
334
334
  * once.
335
335
  */
336
- var MarkdownRenderer = (0, react.memo)(function MarkdownRenderer({ children, className, externalLinkTarget = "tab", streaming = false, tableActions = false }) {
336
+ var MarkdownRenderer = (0, react.memo)(function MarkdownRenderer({ children, className, externalLinkTarget = "tab", streaming = false, tableActions = false, remarkPlugins: extraRemarkPlugins, components: extraComponents }) {
337
337
  const shown = decodeEscapedNewlines(children);
338
338
  const blocks = (0, react.useMemo)(() => splitBlocks(shown), [shown]);
339
339
  const last = blocks.length - 1;
340
- const components = (tableActions ? TABLE_COMPONENTS : DEFAULT_COMPONENTS)[externalLinkTarget];
340
+ const baseComponents = (tableActions ? TABLE_COMPONENTS : DEFAULT_COMPONENTS)[externalLinkTarget];
341
+ const components = (0, react.useMemo)(() => extraComponents ? {
342
+ ...baseComponents,
343
+ ...extraComponents
344
+ } : baseComponents, [baseComponents, extraComponents]);
341
345
  const spans = wordSpans(blocks);
342
346
  const settled = useSettledWords(spans.at(-1)?.end ?? 0, streaming);
343
347
  const settledWords = (span) => !span || settled >= span.end ? void 0 : Math.max(0, settled - span.start);
@@ -350,15 +354,24 @@ var MarkdownRenderer = (0, react.memo)(function MarkdownRenderer({ children, cla
350
354
  settledWords: settledWords(spans[index]),
351
355
  components,
352
356
  streaming,
353
- tableActions
357
+ tableActions,
358
+ extraRemarkPlugins
354
359
  }, index))
355
360
  });
356
361
  });
357
362
  /** Keyed by position at the call site: a content key remounts on every character. */
358
- var MarkdownBlock = (0, react.memo)(function MarkdownBlock({ components, content, settledWords, streaming, tableActions }) {
363
+ var MarkdownBlock = (0, react.memo)(function MarkdownBlock({ components, content, settledWords, streaming, tableActions, extraRemarkPlugins }) {
364
+ const remarkPlugins = (0, react.useMemo)(() => {
365
+ const builtIn = tableActions && !streaming ? COPYABLE_REMARK_PLUGINS : REMARK_PLUGINS;
366
+ return extraRemarkPlugins ? [...builtIn, ...extraRemarkPlugins] : builtIn;
367
+ }, [
368
+ tableActions,
369
+ streaming,
370
+ extraRemarkPlugins
371
+ ]);
359
372
  const rehypePlugins = (0, react.useMemo)(() => settledWords === void 0 ? SETTLED : [rehypeArriving(settledWords)], [settledWords]);
360
373
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_markdown.default, {
361
- remarkPlugins: tableActions && !streaming ? COPYABLE_REMARK_PLUGINS : REMARK_PLUGINS,
374
+ remarkPlugins,
362
375
  rehypePlugins,
363
376
  components,
364
377
  children: content
@@ -474,4 +487,4 @@ Object.defineProperty(exports, "MarkdownRenderer", {
474
487
  }
475
488
  });
476
489
 
477
- //# sourceMappingURL=MarkdownRenderer-CB8Z_CHc.cjs.map
490
+ //# sourceMappingURL=MarkdownRenderer-y65WGBhC.cjs.map