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

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 (212) 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/{MetricsTable-D-aZf3dk.cjs → MetricsTable-BSl81oNe.cjs} +44 -9
  14. package/dist/MetricsTable-BSl81oNe.cjs.map +1 -0
  15. package/dist/{MetricsTable-CRPeLHe1.js → MetricsTable-DID6LRoP.js} +44 -9
  16. package/dist/MetricsTable-DID6LRoP.js.map +1 -0
  17. package/dist/{ask-user-DdYz56qH.cjs → ask-user-C1p2PEYe.cjs} +2 -2
  18. package/dist/ask-user-C1p2PEYe.cjs.map +1 -0
  19. package/dist/{ask-user-B225wzWc.js → ask-user-DPznrqGO.js} +2 -2
  20. package/dist/ask-user-DPznrqGO.js.map +1 -0
  21. package/dist/chart-plot.css +5 -4
  22. package/dist/{combobox-CtCK0mNx.js → combobox-D21no8t5.js} +4 -4
  23. package/dist/{combobox-CtCK0mNx.js.map → combobox-D21no8t5.js.map} +1 -1
  24. package/dist/{combobox-CMx2ayFN.cjs → combobox-DIT_6xiG.cjs} +4 -4
  25. package/dist/combobox-DIT_6xiG.cjs.map +1 -0
  26. package/dist/{combobox-parts-ScKcYjMR.cjs → combobox-parts-C4phOq4t.cjs} +2 -2
  27. package/dist/combobox-parts-C4phOq4t.cjs.map +1 -0
  28. package/dist/{combobox-parts-C1CugUAU.js → combobox-parts-D90ir0Py.js} +3 -3
  29. package/dist/combobox-parts-D90ir0Py.js.map +1 -0
  30. package/dist/components/Combobox.cjs.js +2 -2
  31. package/dist/components/Combobox.es.js +2 -2
  32. package/dist/components/Command.cjs.js +1 -1
  33. package/dist/components/Command.cjs.js.map +1 -1
  34. package/dist/components/Command.es.js +1 -1
  35. package/dist/components/Command.es.js.map +1 -1
  36. package/dist/components/DataCodeSection.cjs.js +1 -1
  37. package/dist/components/DataCodeSection.es.js +1 -1
  38. package/dist/components/DataList.cjs.js +1 -1
  39. package/dist/components/DataList.es.js +1 -1
  40. package/dist/components/DataPanel.cjs.js +1 -1
  41. package/dist/components/DataPanel.es.js +1 -1
  42. package/dist/components/DateTimePicker.cjs.js +1 -1
  43. package/dist/components/DateTimePicker.cjs.js.map +1 -1
  44. package/dist/components/DateTimePicker.es.js +1 -1
  45. package/dist/components/DateTimePicker.es.js.map +1 -1
  46. package/dist/components/FilterBar.cjs.js +3 -3
  47. package/dist/components/FilterBar.es.js +3 -3
  48. package/dist/components/FormFieldBlocks.cjs.js +1 -1
  49. package/dist/components/FormFieldBlocks.cjs.js.map +1 -1
  50. package/dist/components/FormFieldBlocks.es.js +1 -1
  51. package/dist/components/FormFieldBlocks.es.js.map +1 -1
  52. package/dist/components/MetricsTable.cjs.js +1 -1
  53. package/dist/components/MetricsTable.es.js +1 -1
  54. package/dist/components/PropertyFilter.cjs.js +3 -3
  55. package/dist/components/PropertyFilter.cjs.js.map +1 -1
  56. package/dist/components/PropertyFilter.es.js +3 -3
  57. package/dist/components/PropertyFilter.es.js.map +1 -1
  58. package/dist/components/SavedViews.cjs.js +1 -1
  59. package/dist/components/SavedViews.es.js +1 -1
  60. package/dist/components/Sidebar.cjs.js +8 -8
  61. package/dist/components/Sidebar.cjs.js.map +1 -1
  62. package/dist/components/Sidebar.es.js +9 -9
  63. package/dist/components/Sidebar.es.js.map +1 -1
  64. package/dist/components/ai/ask-user.cjs.js +1 -1
  65. package/dist/components/ai/ask-user.es.js +1 -1
  66. package/dist/domains/chat/tools/badges/ask-user-badge.cjs.js +1 -1
  67. package/dist/domains/chat/tools/badges/ask-user-badge.es.js +1 -1
  68. package/dist/domains/dashboards/kinds/table/table-view.cjs.js +1 -1
  69. package/dist/domains/dashboards/kinds/table/table-view.es.js +1 -1
  70. package/dist/domains/dashboards/metrics-dashboard.cjs.js +1 -1
  71. package/dist/domains/dashboards/metrics-dashboard.cjs.js.map +1 -1
  72. package/dist/domains/dashboards/metrics-dashboard.es.js +1 -1
  73. package/dist/domains/dashboards/metrics-dashboard.es.js.map +1 -1
  74. package/dist/domains/datasets/components/save-as-dataset-item-dialog.cjs.js +1 -1
  75. package/dist/domains/datasets/components/save-as-dataset-item-dialog.es.js +1 -1
  76. package/dist/domains/logs/components/log-data-panel.cjs.js +1 -1
  77. package/dist/domains/logs/components/log-data-panel.es.js +1 -1
  78. package/dist/domains/logs/components/logs-saved-views.cjs.js +1 -1
  79. package/dist/domains/logs/components/logs-saved-views.es.js +1 -1
  80. package/dist/domains/logs/components/logs-toolbar.cjs.js +1 -1
  81. package/dist/domains/logs/components/logs-toolbar.es.js +1 -1
  82. package/dist/domains/metrics/components/breakdown/breakdown-table.cjs.js +2 -2
  83. package/dist/domains/metrics/components/breakdown/breakdown-table.cjs.js.map +1 -1
  84. package/dist/domains/metrics/components/breakdown/breakdown-table.es.js +2 -2
  85. package/dist/domains/metrics/components/breakdown/breakdown-table.es.js.map +1 -1
  86. package/dist/domains/metrics/components/metrics-time-range-chip.cjs.js +1 -1
  87. package/dist/domains/metrics/components/metrics-time-range-chip.es.js +1 -1
  88. package/dist/domains/observability/saved-views/observability-saved-views.cjs.js +1 -1
  89. package/dist/domains/observability/saved-views/observability-saved-views.es.js +1 -1
  90. package/dist/domains/observability/saved-views.cjs.js +1 -1
  91. package/dist/domains/observability/saved-views.es.js +1 -1
  92. package/dist/domains/observability.cjs.js +1 -1
  93. package/dist/domains/observability.es.js +1 -1
  94. package/dist/domains/scores/components/score-data-panel.cjs.js +1 -1
  95. package/dist/domains/scores/components/score-data-panel.es.js +1 -1
  96. package/dist/domains/scores/components/span-scoring.cjs.js +3 -3
  97. package/dist/domains/scores/components/span-scoring.cjs.js.map +1 -1
  98. package/dist/domains/scores/components/span-scoring.es.js +3 -3
  99. package/dist/domains/scores/components/span-scoring.es.js.map +1 -1
  100. package/dist/domains/skills/skill-simple-form.cjs.js +1 -1
  101. package/dist/domains/skills/skill-simple-form.cjs.js.map +1 -1
  102. package/dist/domains/skills/skill-simple-form.es.js +1 -1
  103. package/dist/domains/skills/skill-simple-form.es.js.map +1 -1
  104. package/dist/domains/spans/components/spans-explorer-body.cjs.js +1 -1
  105. package/dist/domains/spans/components/spans-explorer-body.es.js +1 -1
  106. package/dist/domains/spans/components/spans-filter-bar.cjs.js +3 -3
  107. package/dist/domains/spans/components/spans-filter-bar.cjs.js.map +1 -1
  108. package/dist/domains/spans/components/spans-filter-bar.es.js +3 -3
  109. package/dist/domains/spans/components/spans-filter-bar.es.js.map +1 -1
  110. package/dist/domains/spans/hooks/use-spans-filter-bar.cjs.js +1 -1
  111. package/dist/domains/spans/hooks/use-spans-filter-bar.es.js +1 -1
  112. package/dist/domains/threads/components/threads-explorer-body.cjs.js +1 -1
  113. package/dist/domains/threads/components/threads-explorer-body.es.js +1 -1
  114. package/dist/domains/threads/components/threads-filter-bar.cjs.js +3 -3
  115. package/dist/domains/threads/components/threads-filter-bar.cjs.js.map +1 -1
  116. package/dist/domains/threads/components/threads-filter-bar.es.js +3 -3
  117. package/dist/domains/threads/components/threads-filter-bar.es.js.map +1 -1
  118. package/dist/domains/threads/hooks/use-threads-filter-bar.cjs.js +1 -1
  119. package/dist/domains/threads/hooks/use-threads-filter-bar.es.js +1 -1
  120. package/dist/domains/traces/components/feedback-thread.cjs.js +1 -1
  121. package/dist/domains/traces/components/feedback-thread.cjs.js.map +1 -1
  122. package/dist/domains/traces/components/feedback-thread.es.js +1 -1
  123. package/dist/domains/traces/components/feedback-thread.es.js.map +1 -1
  124. package/dist/domains/traces/components/span-data-panel-view.cjs.js +1 -1
  125. package/dist/domains/traces/components/span-data-panel-view.es.js +1 -1
  126. package/dist/domains/traces/components/span-summary-description.cjs.js +1 -1
  127. package/dist/domains/traces/components/span-summary-description.es.js +1 -1
  128. package/dist/domains/traces/components/thread-trace/thread-trace-details.cjs.js +1 -1
  129. package/dist/domains/traces/components/thread-trace/thread-trace-details.es.js +1 -1
  130. package/dist/domains/traces/components/trace-columns-menu.cjs.js +3 -3
  131. package/dist/domains/traces/components/trace-columns-menu.cjs.js.map +1 -1
  132. package/dist/domains/traces/components/trace-columns-menu.es.js +3 -3
  133. package/dist/domains/traces/components/trace-columns-menu.es.js.map +1 -1
  134. package/dist/domains/traces/components/trace-data-panel-view.cjs.js +2 -2
  135. package/dist/domains/traces/components/trace-data-panel-view.cjs.js.map +1 -1
  136. package/dist/domains/traces/components/trace-data-panel-view.es.js +2 -2
  137. package/dist/domains/traces/components/trace-data-panel-view.es.js.map +1 -1
  138. package/dist/domains/traces/components/trace-id-button.cjs.js +1 -1
  139. package/dist/domains/traces/components/trace-id-button.es.js +1 -1
  140. package/dist/domains/traces/components/trace-summary-description.cjs.js +1 -1
  141. package/dist/domains/traces/components/trace-summary-description.es.js +1 -1
  142. package/dist/domains/traces/components/trace-thread-panel.cjs.js +1 -1
  143. package/dist/domains/traces/components/trace-thread-panel.es.js +1 -1
  144. package/dist/domains/traces/components/traces-explorer/traces-explorer-filter-bar.cjs.js +3 -3
  145. package/dist/domains/traces/components/traces-explorer/traces-explorer-filter-bar.cjs.js.map +1 -1
  146. package/dist/domains/traces/components/traces-explorer/traces-explorer-filter-bar.es.js +3 -3
  147. package/dist/domains/traces/components/traces-explorer/traces-explorer-filter-bar.es.js.map +1 -1
  148. package/dist/domains/traces/components/traces-explorer/traces-explorer-saved-views.cjs.js +1 -1
  149. package/dist/domains/traces/components/traces-explorer/traces-explorer-saved-views.es.js +1 -1
  150. package/dist/domains/traces/components/traces-explorer/use-traces-filter-bar.cjs.js +1 -1
  151. package/dist/domains/traces/components/traces-explorer/use-traces-filter-bar.es.js +1 -1
  152. package/dist/domains/workflows/components/workflow-combobox.cjs.js +2 -2
  153. package/dist/domains/workflows/components/workflow-combobox.cjs.js.map +1 -1
  154. package/dist/domains/workflows/components/workflow-combobox.es.js +2 -2
  155. package/dist/domains/workflows/components/workflow-combobox.es.js.map +1 -1
  156. package/dist/domains/workflows/workflow/input/workflow-processor-input.cjs.js +1 -1
  157. package/dist/domains/workflows/workflow/input/workflow-processor-input.cjs.js.map +1 -1
  158. package/dist/domains/workflows/workflow/input/workflow-processor-input.es.js +1 -1
  159. package/dist/domains/workflows/workflow/input/workflow-processor-input.es.js.map +1 -1
  160. package/dist/domains/workspace/components/workspace-add-skill-dialog.cjs.js +1 -1
  161. package/dist/domains/workspace/components/workspace-add-skill-dialog.cjs.js.map +1 -1
  162. package/dist/domains/workspace/components/workspace-add-skill-dialog.es.js +1 -1
  163. package/dist/domains/workspace/components/workspace-add-skill-dialog.es.js.map +1 -1
  164. package/dist/{filter-bar-chip-B4sV4gDm.js → filter-bar-chip-CABeKrtf.js} +4 -4
  165. package/dist/{filter-bar-chip-B4sV4gDm.js.map → filter-bar-chip-CABeKrtf.js.map} +1 -1
  166. package/dist/{filter-bar-chip-CIEsWcEw.cjs → filter-bar-chip-Cg-UbIwP.cjs} +4 -4
  167. package/dist/{filter-bar-chip-CIEsWcEw.cjs.map → filter-bar-chip-Cg-UbIwP.cjs.map} +1 -1
  168. package/dist/{filter-bar-time-range-DvuaFnkI.cjs → filter-bar-time-range-BA-pXMlo.cjs} +2 -2
  169. package/dist/{filter-bar-time-range-DvuaFnkI.cjs.map → filter-bar-time-range-BA-pXMlo.cjs.map} +1 -1
  170. package/dist/{filter-bar-time-range-CXQMBgpz.js → filter-bar-time-range-mg9JeYue.js} +2 -2
  171. package/dist/{filter-bar-time-range-CXQMBgpz.js.map → filter-bar-time-range-mg9JeYue.js.map} +1 -1
  172. package/dist/layout/tabbed-container.cjs.js +1 -1
  173. package/dist/layout/tabbed-container.es.js +1 -1
  174. package/dist/{observability-saved-views-BBam8Fr5.js → observability-saved-views-CjKTEp1V.js} +3 -3
  175. package/dist/observability-saved-views-CjKTEp1V.js.map +1 -0
  176. package/dist/{observability-saved-views-BAzxxoAr.cjs → observability-saved-views-Daizz4tU.cjs} +3 -3
  177. package/dist/observability-saved-views-Daizz4tU.cjs.map +1 -0
  178. package/dist/primitives/chart-plot.cjs.js +8 -6
  179. package/dist/primitives/chart-plot.cjs.js.map +1 -1
  180. package/dist/primitives/chart-plot.es.js +8 -6
  181. package/dist/primitives/chart-plot.es.js.map +1 -1
  182. package/dist/primitives/control-icon.cjs.js.map +1 -1
  183. package/dist/primitives/control-icon.es.js.map +1 -1
  184. package/dist/{property-filter-applied-p3dTTDdb.js → property-filter-applied--U5EZdaA.js} +2 -2
  185. package/dist/property-filter-applied--U5EZdaA.js.map +1 -0
  186. package/dist/{property-filter-applied-BCeRLcXb.cjs → property-filter-applied-BkkIObRq.cjs} +2 -2
  187. package/dist/property-filter-applied-BkkIObRq.cjs.map +1 -0
  188. package/dist/src/ds/components/MetricsTable/metrics-table-rows.d.ts +10 -3
  189. package/dist/src/ds/components/MetricsTable/metrics-table.d.ts +1 -1
  190. package/dist/style.css +14 -1
  191. package/dist/{tabbed-container-DQU7pVio.cjs → tabbed-container-B4lCBgRP.cjs} +2 -2
  192. package/dist/{tabbed-container-DQU7pVio.cjs.map → tabbed-container-B4lCBgRP.cjs.map} +1 -1
  193. package/dist/{tabbed-container-5j6dhoRX.js → tabbed-container-DI1GI1Qv.js} +2 -2
  194. package/dist/{tabbed-container-5j6dhoRX.js.map → tabbed-container-DI1GI1Qv.js.map} +1 -1
  195. package/oxlint/index.js +90 -0
  196. package/package.json +8 -8
  197. package/theme.css +4 -3
  198. package/dist/DataCodeSection-CcPmJPTp.cjs.map +0 -1
  199. package/dist/DataCodeSection-KJRyRD1Q.js.map +0 -1
  200. package/dist/FilterBar-BO-vvvyq.js.map +0 -1
  201. package/dist/FilterBar-Buw0tv51.cjs.map +0 -1
  202. package/dist/MetricsTable-CRPeLHe1.js.map +0 -1
  203. package/dist/MetricsTable-D-aZf3dk.cjs.map +0 -1
  204. package/dist/ask-user-B225wzWc.js.map +0 -1
  205. package/dist/ask-user-DdYz56qH.cjs.map +0 -1
  206. package/dist/combobox-CMx2ayFN.cjs.map +0 -1
  207. package/dist/combobox-parts-C1CugUAU.js.map +0 -1
  208. package/dist/combobox-parts-ScKcYjMR.cjs.map +0 -1
  209. package/dist/observability-saved-views-BAzxxoAr.cjs.map +0 -1
  210. package/dist/observability-saved-views-BBam8Fr5.js.map +0 -1
  211. package/dist/property-filter-applied-BCeRLcXb.cjs.map +0 -1
  212. package/dist/property-filter-applied-p3dTTDdb.js.map +0 -1
@@ -1 +0,0 @@
1
- {"version":3,"file":"combobox-parts-ScKcYjMR.cjs","names":["cn","buttonVariants","isIconButtonSize","controlTriggerOpenState","fieldTriggerErrorBorder","cva","menuItemClass","menuPopupClass","menuPositionerClass","menuSearchClasses","menuEmptyClass","menuItemCheckClass","BaseCombobox","cn","ChevronDown","isIconButtonSize","_Fragment","ButtonIcon","TriggerChevron","ButtonChevron","X","passwordManagerOptOutProps","Search","usePopupAnchor","usePortalContainer","FLOATING_POSITION_METHOD","ScrollArea","ScrollAreaViewport","Check","menuLabelClass","menuSeparatorClass","React"],"sources":["../src/ds/components/Combobox/combobox-styles.ts","../src/ds/components/Combobox/combobox-parts.tsx"],"sourcesContent":["import { cva } from 'class-variance-authority';\nimport { buttonVariants, isIconButtonSize } from '../Button/Button';\nimport type { ButtonSize } from '../Button/Button';\nimport { controlTriggerOpenState } from '@/ds/primitives/control-size';\nimport type { ControlTriggerVisualVariant } from '@/ds/primitives/control-size';\nimport { fieldTriggerErrorBorder, fieldTriggerStyle, fieldTriggerWidthStyle } from '@/ds/primitives/form-element';\nimport {\n menuItemCheckClass,\n menuItemClass,\n menuPopupClass,\n menuPositionerClass,\n menuSearchClasses,\n menuEmptyClass,\n} from '@/ds/primitives/menu-item';\nimport { cn } from '@/lib/utils';\n\n/**\n * A combobox is a form field, so it reuses the Button's size/shape recipe,\n * mirroring `SelectTrigger`: `default` (the Input's overlay surface — the\n * default here too) and `ghost` (borderless, for breadcrumbs/inline pickers). Only the high-emphasis `primary`\n * look is intentionally NOT offered (a field is not a call-to-action).\n */\nexport type ComboboxVisualVariant = ControlTriggerVisualVariant;\nexport type ComboboxLegacyVariant = 'link';\nexport type ComboboxVariant = ComboboxVisualVariant | ComboboxLegacyVariant;\n\nfunction normalizeComboboxVariant(variant: ComboboxVariant): ComboboxVisualVariant {\n return variant === 'link' ? 'ghost' : variant;\n}\n\n/**\n * Single source of truth for both the single- and multi-select combobox\n * triggers. A combobox = a button + a trailing chevron, so it reuses the Button\n * recipe (variant colors, size = height/text/padding/radius, unified border\n * focus, disabled) and layers only the combobox-specific extras — exactly like\n * `SelectTrigger`.\n */\nexport function comboboxTriggerClass({\n variant,\n size,\n className,\n}: {\n variant: ComboboxVariant;\n size: ButtonSize;\n className?: string;\n}): string {\n const visualVariant = normalizeComboboxVariant(variant);\n\n return cn(\n buttonVariants({ variant: visualVariant, size }),\n visualVariant === 'default' && fieldTriggerStyle,\n // Fill the field and push the value left / chevron right (Button's base\n // centers its content with `justify-center`). Icon sizes are a fixed square\n // showing only the chevron, so they keep Button's centering.\n !isIconButtonSize(size) && cn(fieldTriggerWidthStyle, 'justify-between'),\n // Read as \"active\" while the popup is open, per variant (see map above).\n controlTriggerOpenState[visualVariant],\n 'data-[placeholder]:text-muted-foreground',\n fieldTriggerErrorBorder,\n className,\n );\n}\n\n/** Options are shared menu items, which already grow to fit a second line. */\nexport const comboboxItemClass = cva(menuItemClass, {\n variants: {\n multiple: {\n false: '',\n true: '',\n },\n },\n defaultVariants: {\n multiple: false,\n },\n});\n\nexport const comboboxStyles = {\n /** @deprecated A `Field` lays out the combobox and its error. */\n root: 'flex flex-col gap-1.5',\n\n /** Chevron icon in trigger — decorative icon token shared by every field. */\n\n /** Placeholder text color */\n placeholder: 'text-muted-foreground',\n\n /**\n * Popup container — shared menu popup, but the search row sits edge-to-edge\n * above the list, so padding/scrolling move to the list itself.\n */\n popup: cn(menuPopupClass, 'max-h-none overflow-hidden p-0'),\n\n /** Positioner */\n positioner: cn(menuPositionerClass, 'pointer-events-auto'),\n\n /** Search input container — borderless top section, hairline divider below. */\n searchContainer: menuSearchClasses.container,\n\n /** Search icon */\n searchIcon: menuSearchClasses.icon,\n\n /** Search input */\n searchInput: cn(menuSearchClasses.input, 'disabled:cursor-not-allowed disabled:opacity-50'),\n\n /** Empty state */\n empty: cn(menuEmptyClass, 'empty:hidden'),\n\n /** Options list */\n // `empty:p-0` — Empty renders outside the List, so an empty List must not leave its padding behind.\n list: 'p-1 empty:p-0',\n\n /** Scroll container around the List. */\n listScroller: 'max-h-dropdown overflow-y-auto overflow-x-hidden',\n\n /** Option item base — rounded-lg sits concentrically inside rounded-xl + p-1. */\n item: comboboxItemClass({ multiple: false }),\n\n /** Multi-select item — same item rhythm with a right-aligned selected check. */\n itemMulti: comboboxItemClass({ multiple: true }),\n\n /** Right-aligned slot grouping end content + selection check. */\n itemRightSlot: 'ml-auto flex items-center gap-2 shrink-0',\n\n /** Check indicator container — inline, shown only when item is selected. */\n checkContainer: cn(menuItemCheckClass, 'ml-0'),\n\n /** Check icon (single select) */\n checkIcon: 'size-full',\n\n /** Option label/description wrapper */\n optionText: 'flex flex-col gap-0.5 min-w-0',\n\n /** Option label */\n optionLabel: 'truncate',\n\n /** Option description */\n optionDescription: 'text-caption text-muted-foreground truncate',\n\n /** Option end slot — `ml-auto` makes it push right inside flex containers (used by multi-select). */\n optionEnd: 'ml-auto flex items-center shrink-0',\n\n /** @deprecated A `FieldError` colors the error. */\n error: 'text-body-sm text-destructive-foreground',\n} as const;\n","// Composable Combobox parts: shadcn's structure and names (https://ui.shadcn.com/docs/components/combobox),\n// built on Base UI like theirs, styled with our design system. The root is `ComboboxRoot` because\n// `Combobox` is the options-driven component in combobox.tsx.\nimport { Combobox as BaseCombobox } from '@base-ui/react/combobox';\nimport { Check, ChevronDown, Search, X } from 'lucide-react';\nimport * as React from 'react';\nimport { comboboxItemClass, comboboxStyles, comboboxTriggerClass } from './combobox-styles';\nimport type { ComboboxVariant } from './combobox-styles';\nimport { ButtonChevron, ButtonIcon, TriggerChevron, isIconButtonSize } from '@/ds/components/Button/Button';\nimport type { ButtonSize, TextButtonSize } from '@/ds/components/Button/Button';\nimport { ScrollArea, ScrollAreaViewport } from '@/ds/components/ScrollArea';\nimport { FLOATING_POSITION_METHOD } from '@/ds/primitives/floating';\nimport { menuLabelClass, menuSeparatorClass } from '@/ds/primitives/menu-item';\nimport { passwordManagerOptOutProps } from '@/ds/primitives/password-manager-autofill';\nimport { usePopupAnchor } from '@/ds/primitives/popup-anchor';\nimport { usePortalContainer } from '@/ds/primitives/portal-container';\nimport type { PortalContainer } from '@/ds/primitives/portal-container';\nimport { cn } from '@/lib/utils';\n\n/**\n * Root. Same props as Base UI's `Combobox.Root` (`items`, `value`, `onValueChange`, `multiple`,\n * `autoHighlight`, `filter`, ...). Pick one of three shapes:\n * - Search in the field: `ComboboxInput` + `ComboboxContent`.\n * - Multiple, chips in the field: `ComboboxChips` (chips + `ComboboxChipsInput`) + `ComboboxContent`.\n * - Compact trigger, search in the popup: `ComboboxTrigger` + `ComboboxContent` starting with\n * `ComboboxSearch`. For small triggers (an icon, a ghost button in a toolbar).\n */\nfunction ComboboxRoot<Value, Multiple extends boolean | undefined = false>(\n props: BaseCombobox.Root.Props<Value, Multiple>,\n) {\n return <BaseCombobox.Root {...props} />;\n}\n\n/**\n * The field surface: today's trigger look, focus shown while the input inside has focus. The\n * chevron ends every field, at the same padding as today's Combobox trigger.\n */\nconst fieldClass = (size: TextButtonSize = 'md') =>\n cn(\n comboboxTriggerClass({ variant: 'default', size }),\n 'cursor-text gap-2 focus-within:[--surface-rim:var(--field-rim-focus)]',\n // Disabled like other form elements (muted text, not-allowed cursor), keyed off the input.\n 'has-[input:disabled]:cursor-not-allowed has-[input:disabled]:bg-field-disabled has-[input:disabled]:[&_*]:cursor-not-allowed has-[input:disabled]:[&_*]:text-muted-foreground',\n // The input inside carries `aria-invalid`; the field shows it like other invalid fields.\n 'has-[[aria-invalid=true]]:[--field-rim-focus:var(--destructive-indicator)] has-[[aria-invalid=true]]:[--field-rim:var(--destructive-indicator)]',\n );\n\n/**\n * Text starts 0.9em in (the Button recipe's padding, shared with Select and today's Combobox).\n * The chevron is a 22px circle; its arrow's ink sits 6.33px inside the circle's edge (3px circle\n * inset + 3.33px icon inset), so the end padding puts that ink 0.9em from the end, like the text.\n */\nconst fieldPx = '0.9em';\n\n/** Inline so it wins over the Button recipe's `px` (same layer, later in the sheet). */\nconst fieldStyle: React.CSSProperties = {\n paddingInlineStart: fieldPx,\n paddingInlineEnd: `calc(${fieldPx} - 6.33px)`,\n};\n\n/**\n * Chips sit 4px from the field's edge on top, bottom and left: 3px visible inside the 1px rim,\n * the same 3px as the gap between chips. A chip is the field height minus that padding (22px).\n */\nconst chipsFieldStyle: React.CSSProperties = {\n // Longhands only: a `padding` shorthand here would also reset the chevron's end padding.\n paddingBlock: '4px',\n paddingInlineStart: '4px',\n paddingInlineEnd: fieldStyle.paddingInlineEnd,\n};\n\n// `w-0` + `flex-1`: an input's default width (about 20 characters) would otherwise set the field's\n// minimum width, so it couldn't shrink into a narrow column.\nconst inputClass =\n 'h-full w-0 min-w-0 flex-1 bg-transparent text-foreground outline-none placeholder:text-muted-foreground';\n\n/** Caret at the end of the value instead of selecting it, the way a text field behaves. */\nfunction moveCaretToEnd(event: React.FocusEvent<HTMLInputElement>) {\n const input = event.currentTarget;\n // Deferred one frame so it runs after the click places the caret; clicking the label lands here too.\n requestAnimationFrame(() => input.setSelectionRange(input.value.length, input.value.length));\n}\n\n/**\n * The selected value, for a compact `ComboboxTrigger` or a custom display. `children` can be a\n * function of the value; `placeholder` shows while nothing is selected.\n */\nfunction ComboboxValue(props: BaseCombobox.Value.Props) {\n return <BaseCombobox.Value data-slot=\"combobox-value\" {...props} />;\n}\n\n/** The round chevron button that ends ComboboxInput and ComboboxChips. */\nfunction ComboboxFieldTrigger() {\n return (\n <BaseCombobox.Trigger\n data-slot=\"combobox-field-trigger\"\n aria-label=\"Show options\"\n // A round button target: the circle fills on hover, the chevron keeps its color.\n className=\"flex size-5.5 shrink-0 cursor-pointer items-center justify-center rounded-full text-muted-foreground not-data-disabled:hover:bg-fill\"\n >\n {/* Sized like Select's chevron: outside the icon rung, so it keeps Lucide's default stroke\n (1.33px at 16px) instead of the rung's 1px. */}\n <ChevronDown className=\"size-4\" />\n </BaseCombobox.Trigger>\n );\n}\n\ntype ComboboxTriggerProps = Omit<BaseCombobox.Trigger.Props, 'className'> & {\n className?: string;\n /** The Button-recipe look, like Select: `default` (field surface), `outline` or `ghost`. */\n variant?: ComboboxVariant;\n /** Icon sizes (`icon-*`) show only `icon` (or the chevron); `children` stay as accessible text. */\n size?: ButtonSize;\n /** Shown before the value, or alone at icon sizes (e.g. a filter icon), replacing the chevron there. */\n icon?: React.ReactNode;\n showChevron?: boolean;\n};\n\n/**\n * A compact trigger that opens the list, with the search inside the popup (`ComboboxSearch`). For\n * small triggers such as an icon or a ghost button; a form field uses ComboboxInput instead.\n * `children` is what the trigger shows, usually `<ComboboxValue placeholder=\"…\" />`.\n */\nfunction ComboboxTrigger({\n className,\n children,\n variant = 'default',\n size = 'md',\n icon,\n showChevron = !(icon && isIconButtonSize(size)),\n ...props\n}: ComboboxTriggerProps) {\n const iconOnly = isIconButtonSize(size);\n return (\n <BaseCombobox.Trigger\n data-slot=\"combobox-trigger\"\n data-shape={iconOnly ? 'icon' : undefined}\n className={comboboxTriggerClass({ variant, size, className })}\n {...props}\n >\n {isIconButtonSize(size) ? (\n <>\n {icon}\n <span className=\"sr-only\">{children}</span>\n </>\n ) : (\n <>\n {icon && <ButtonIcon size={size}>{icon}</ButtonIcon>}\n <span className=\"min-w-0 flex-1 truncate text-left\">{children}</span>\n </>\n )}\n {showChevron && (iconOnly ? <TriggerChevron /> : <ButtonChevron size={size} />)}\n </BaseCombobox.Trigger>\n );\n}\n\n/** An × that clears the value. ComboboxInput renders it with `showClear`. */\nfunction ComboboxClear({ className, ...props }: BaseCombobox.Clear.Props) {\n return (\n <BaseCombobox.Clear\n data-slot=\"combobox-clear\"\n aria-label=\"Clear\"\n className={cn(\n 'flex size-4 shrink-0 items-center justify-center rounded-full text-muted-foreground hover:text-foreground',\n className,\n )}\n {...props}\n >\n <X className=\"size-3.5\" />\n </BaseCombobox.Clear>\n );\n}\n\ntype ComboboxInputProps = Omit<BaseCombobox.Input.Props, 'size'> & {\n /** The field height, from the control sizes. `md` by default. */\n size?: TextButtonSize;\n /** Shown before the text, e.g. the selected item's icon. */\n start?: React.ReactNode;\n /** The chevron button at the end. On by default. */\n showTrigger?: boolean;\n /** An × before the chevron that clears the value. */\n showClear?: boolean;\n};\n\n/**\n * The field you type in to filter, showing the selected value while it's closed. `children` render\n * inside the field before the chevron (e.g. a muted \"4 items\" detail). The list opens at the\n * field's width. Inside a `Field`, the label and errors link to it.\n */\nfunction ComboboxInput({\n className,\n children,\n showTrigger = true,\n showClear = false,\n size,\n start,\n onFocus,\n ...props\n}: ComboboxInputProps) {\n return (\n <BaseCombobox.InputGroup data-slot=\"combobox-input\" className={cn(fieldClass(size), className)} style={fieldStyle}>\n {start ? <span className=\"flex shrink-0 items-center\">{start}</span> : null}\n <BaseCombobox.Input\n onFocus={event => {\n moveCaretToEnd(event);\n onFocus?.(event);\n }}\n className={inputClass}\n {...passwordManagerOptOutProps}\n {...props}\n />\n {children ? <span className=\"flex shrink-0 items-center gap-2 text-muted-foreground\">{children}</span> : null}\n {showClear ? <ComboboxClear /> : null}\n {showTrigger ? <ComboboxFieldTrigger /> : null}\n </BaseCombobox.InputGroup>\n );\n}\n\n/**\n * The search row at the top of the popup, for a compact `ComboboxTrigger`. The same row as today's\n * Combobox: a search icon, a borderless input and a hairline under it.\n */\nfunction ComboboxSearch({ className, ...props }: BaseCombobox.Input.Props) {\n return (\n <div data-slot=\"combobox-search\" className={comboboxStyles.searchContainer}>\n <Search className={comboboxStyles.searchIcon} />\n <BaseCombobox.Input\n className={cn(comboboxStyles.searchInput, className)}\n {...passwordManagerOptOutProps}\n {...props}\n />\n </div>\n );\n}\n\ntype ComboboxContentProps = BaseCombobox.Popup.Props &\n Pick<BaseCombobox.Positioner.Props, 'side' | 'align' | 'sideOffset' | 'alignOffset' | 'anchor'> & {\n /** Where the popup portals to. Defaults to the nearest dialog or drawer, so it stays interactive there. */\n container?: PortalContainer;\n };\n\n/**\n * The popup. Under a field (ComboboxInput or ComboboxChips) it opens at the field's width; under a\n * compact ComboboxTrigger it takes the trigger's width, at least 11rem. Either way the width never\n * follows the filtered items, so it holds still while you type; long labels truncate.\n */\nfunction ComboboxContent({\n className,\n side = 'bottom',\n sideOffset = 4,\n align = 'start',\n alignOffset = 0,\n anchor,\n container,\n ...props\n}: ComboboxContentProps) {\n const popupAnchor = usePopupAnchor();\n const resolvedContainer = usePortalContainer(container);\n return (\n <BaseCombobox.Portal container={resolvedContainer}>\n <BaseCombobox.Positioner\n side={side}\n sideOffset={sideOffset}\n align={align}\n alignOffset={alignOffset}\n // Base UI anchors to the field (the InputGroup of ComboboxInput or ComboboxChips), or to the\n // trigger when the input is in the popup; a crumb switcher anchors to the whole crumb.\n anchor={anchor ?? popupAnchor}\n positionMethod={FLOATING_POSITION_METHOD}\n className={comboboxStyles.positioner}\n >\n <BaseCombobox.Popup\n data-slot=\"combobox-content\"\n // With the popup's `min-w-[max(11rem,var(--anchor-width))]`: the anchor's width, at least 11rem.\n className={cn(comboboxStyles.popup, 'w-(--anchor-width)', className)}\n {...props}\n />\n </BaseCombobox.Positioner>\n </BaseCombobox.Portal>\n );\n}\n\n/** The scrolling list. Children: a render function per item (or per group), like Base UI's List. */\nfunction ComboboxList({ className, ...props }: BaseCombobox.List.Props) {\n return (\n <ScrollArea maxHeight=\"var(--spacing-dropdown)\">\n <ScrollAreaViewport className=\"scroll-py-8\">\n <BaseCombobox.List data-slot=\"combobox-list\" className={cn(comboboxStyles.list, className)} {...props} />\n </ScrollAreaViewport>\n </ScrollArea>\n );\n}\n\n/** One option. A check shows on the right while it's selected. */\nfunction ComboboxItem({ className, children, ref, ...props }: BaseCombobox.Item.Props) {\n return (\n <BaseCombobox.Item ref={ref} data-slot=\"combobox-item\" className={cn(comboboxItemClass({}), className)} {...props}>\n <span className=\"flex min-w-0 flex-1 items-center gap-2\">{children}</span>\n <span className={comboboxStyles.checkContainer}>\n <BaseCombobox.ItemIndicator>\n <Check className={comboboxStyles.checkIcon} />\n </BaseCombobox.ItemIndicator>\n </span>\n </BaseCombobox.Item>\n );\n}\n\n/** Title over a description inside an item (shadcn's Item / ItemTitle / ItemDescription). */\nfunction ComboboxItemContent({ className, ...props }: React.ComponentProps<'span'>) {\n return (\n <span data-slot=\"combobox-item-content\" className={cn('flex min-w-0 flex-col gap-0.5', className)} {...props} />\n );\n}\n\nfunction ComboboxItemTitle({ className, ...props }: React.ComponentProps<'span'>) {\n return <span data-slot=\"combobox-item-title\" className={cn('truncate', className)} {...props} />;\n}\n\n/** Muted, up to two lines. */\nfunction ComboboxItemDescription({ className, ...props }: React.ComponentProps<'span'>) {\n return (\n <span\n data-slot=\"combobox-item-description\"\n // `whitespace-normal`: the item recipe's `[&>span]:truncate` makes its content `nowrap`, which\n // would cut the description off mid-word on one line instead of clamping it at two.\n className={cn('line-clamp-2 text-caption whitespace-normal text-muted-foreground', className)}\n {...props}\n />\n );\n}\n\n/** Muted text at the end of an item, e.g. its kind (\"Agent\"). */\nfunction ComboboxItemEnd({ className, ...props }: React.ComponentProps<'span'>) {\n return (\n <span\n data-slot=\"combobox-item-end\"\n className={cn('ml-auto shrink-0 text-caption text-muted-foreground', className)}\n {...props}\n />\n );\n}\n\n/** A section of items. Pass the section's `items`; render them with ComboboxCollection. */\nfunction ComboboxGroup(props: BaseCombobox.Group.Props) {\n return <BaseCombobox.Group data-slot=\"combobox-group\" {...props} />;\n}\n\n/** A group's heading, styled like menu section labels. */\nfunction ComboboxLabel({ className, ...props }: BaseCombobox.GroupLabel.Props) {\n return <BaseCombobox.GroupLabel data-slot=\"combobox-label\" className={cn(menuLabelClass, className)} {...props} />;\n}\n\n/** Renders a group's filtered items, one render function call per item. */\nfunction ComboboxCollection(props: BaseCombobox.Collection.Props) {\n return <BaseCombobox.Collection data-slot=\"combobox-collection\" {...props} />;\n}\n\n/** Shows its children only when the filter matches nothing. */\nfunction ComboboxEmpty({ className, ...props }: BaseCombobox.Empty.Props) {\n return <BaseCombobox.Empty data-slot=\"combobox-empty\" className={cn(comboboxStyles.empty, className)} {...props} />;\n}\n\nfunction ComboboxSeparator({ className, ...props }: BaseCombobox.Separator.Props) {\n return (\n <BaseCombobox.Separator data-slot=\"combobox-separator\" className={cn(menuSeparatorClass, className)} {...props} />\n );\n}\n\n/**\n * Multi-select field: chips for the picked items, then ComboboxChipsInput. The chips and input wrap\n * inside their own area so the chevron keeps its place on the first row. While the field is one\n * line it keeps the pill shape of every other field; once chips wrap it takes the Textarea corner.\n */\nfunction ComboboxChips({ className, children, 'aria-label': ariaLabel, ...props }: BaseCombobox.InputGroup.Props) {\n // On the inner chips area, so a caller's `ref` reaches the field without merging refs.\n const chipsRef = React.useRef<HTMLDivElement>(null);\n const [multiline, setMultiline] = React.useState(false);\n\n React.useLayoutEffect(() => {\n const field = chipsRef.current?.parentElement;\n // No observer (e.g. jsdom in tests): the field keeps its one-row shape.\n if (!field || typeof ResizeObserver === 'undefined') return;\n // One row is the control height (the field's `min-height`); anything taller means the chips wrapped.\n // The 1px slack absorbs subpixel rounding.\n const rowHeight = parseFloat(getComputedStyle(field).minHeight) || 0;\n const observer = new ResizeObserver(() => setMultiline(field.offsetHeight > rowHeight + 1));\n observer.observe(field);\n return () => observer.disconnect();\n }, []);\n\n // Chips inside an InputGroup, like Base UI's multi-select example: the popup anchors to the group.\n return (\n <BaseCombobox.InputGroup\n data-slot=\"combobox-chips\"\n data-multiline={multiline ? '' : undefined}\n style={chipsFieldStyle}\n className={cn(\n fieldClass(),\n 'h-auto min-h-control-md items-start data-multiline:rounded-xl',\n // The chips field keeps its resting look: no open tint, no placeholder color. InputGroup sets those\n // attributes, which the trigger recipe styles.\n 'data-[placeholder]:text-foreground data-[popup-open]:[--surface-tint:transparent]',\n className,\n )}\n {...props}\n >\n {/* The label names the chips toolbar, as it did when Chips was the outer element. */}\n <BaseCombobox.Chips ref={chipsRef} aria-label={ariaLabel} className=\"flex min-w-0 flex-1 flex-wrap gap-[3px]\">\n {children}\n </BaseCombobox.Chips>\n {/* Same height as a chip, so the chevron centers on the first row. */}\n <span className=\"flex h-5.5 shrink-0 items-center\">\n <ComboboxFieldTrigger />\n </span>\n </BaseCombobox.InputGroup>\n );\n}\n\n/** One picked item inside ComboboxChips. The × (or Backspace in the input) removes it. */\nfunction ComboboxChip({\n className,\n children,\n showRemove = true,\n ...props\n}: BaseCombobox.Chip.Props & { showRemove?: boolean }) {\n return (\n <BaseCombobox.Chip\n data-slot=\"combobox-chip\"\n className={cn(\n // 8px from the left edge to the text, 6px from the text to the ×'s ink, 8px from the ink to\n // the right edge. Text in the controls' role (`text-label`), like the field value.\n 'flex h-5.5 items-center rounded-full bg-fill pl-2 text-label text-foreground',\n !showRemove && 'pr-2',\n className,\n )}\n {...props}\n >\n {children}\n {showRemove ? (\n <BaseCombobox.ChipRemove\n data-slot=\"combobox-chip-remove\"\n aria-label={typeof children === 'string' ? `Remove ${children}` : 'Remove'}\n // The whole right end is the hit area: full height, from the gap to the chip's edge. The ×'s\n // ink sits 2.5px inside its 12px icon, so 3.5px / 5.5px padding put it 6px / 8px out.\n className=\"flex h-full cursor-pointer items-center rounded-r-full pr-[5.5px] pl-[3.5px] text-muted-foreground not-data-disabled:hover:text-foreground\"\n >\n {/* Inline so the button's color wins over the field's `[&_svg]` icon colors. */}\n <X className=\"size-3\" style={{ color: 'inherit' }} />\n </BaseCombobox.ChipRemove>\n ) : null}\n </BaseCombobox.Chip>\n );\n}\n\n/** The text input after the chips in ComboboxChips. */\nfunction ComboboxChipsInput({ className, onFocus, ...props }: BaseCombobox.Input.Props) {\n return (\n <BaseCombobox.Input\n data-slot=\"combobox-chip-input\"\n onFocus={event => {\n moveCaretToEnd(event);\n onFocus?.(event);\n }}\n className={cn(\n inputClass,\n // Text lines up with other fields' text when there are no chips; 4px after a chip otherwise.\n // Not `first:`: Base UI inserts a hidden Dismiss element before the input while open.\n 'h-5.5 w-0 min-w-12 flex-1 pl-[calc(0.9em_-_4px)] [[data-slot=combobox-chip]~&]:pl-1',\n className,\n )}\n {...passwordManagerOptOutProps}\n {...props}\n />\n );\n}\n\nexport type { ComboboxTriggerProps, ComboboxInputProps, ComboboxContentProps };\n\nexport {\n ComboboxRoot,\n ComboboxInput,\n ComboboxTrigger,\n ComboboxSearch,\n ComboboxValue,\n ComboboxClear,\n ComboboxContent,\n ComboboxList,\n ComboboxItem,\n ComboboxItemContent,\n ComboboxItemTitle,\n ComboboxItemDescription,\n ComboboxItemEnd,\n ComboboxGroup,\n ComboboxLabel,\n ComboboxCollection,\n ComboboxEmpty,\n ComboboxSeparator,\n ComboboxChips,\n ComboboxChip,\n ComboboxChipsInput,\n};\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"observability-saved-views-BAzxxoAr.cjs","names":["useRef","useState","cn","Txt","Button","ComboboxRoot","ComboboxTrigger","LayersIcon","ComboboxContent","ComboboxSearch","ComboboxEmpty","ComboboxList","ComboboxItem","ComboboxItemEnd","DropdownMenu","EllipsisIcon","TextCursorInputIcon","CopyIcon","_Fragment","Trash2Icon","Popover","PopoverTrigger","LayersPlusIcon","PopoverContent","Field","Input","FieldError","useSavedViewsSource","useObservabilityHeaderSlot","useHostedSavedViews","createPortal"],"sources":["../src/ds/components/SavedViews/saved-view-picker.tsx","../src/domains/observability/saved-views/observability-saved-views.tsx"],"sourcesContent":["import { CopyIcon, EllipsisIcon, LayersIcon, LayersPlusIcon, TextCursorInputIcon, Trash2Icon } from 'lucide-react';\nimport { useRef, useState } from 'react';\nimport type { FormEvent, ReactNode, RefObject } from 'react';\nimport { MAX_SAVED_VIEW_NAME_CHARS } from './saved-view-schema';\nimport type { SavedView } from './saved-view-schema';\nimport type { SavedViewsController } from './use-saved-views';\nimport { Button } from '@/ds/components/Button/Button';\nimport {\n ComboboxContent,\n ComboboxEmpty,\n ComboboxItem,\n ComboboxItemEnd,\n ComboboxList,\n ComboboxRoot,\n ComboboxSearch,\n ComboboxTrigger,\n} from '@/ds/components/Combobox/combobox-parts';\nimport { DropdownMenu } from '@/ds/components/DropdownMenu';\nimport { Field, FieldError } from '@/ds/components/Field';\nimport { Input } from '@/ds/components/Input/input';\nimport { Popover, PopoverContent, PopoverTrigger } from '@/ds/components/Popover';\nimport { Txt } from '@/ds/components/Txt';\nimport { cn } from '@/lib/utils';\n\nexport type SavedViewPickerProps<TSettings> = {\n views: SavedViewsController<TSettings>;\n /** Names the page's unfiltered state, e.g. \"All traces\". */\n defaultLabel: string;\n newViewSettings: NoInfer<TSettings>;\n /** Muted text after a view in the list, e.g. \"Shared\". */\n describeView?: (view: SavedView<TSettings>) => ReactNode;\n /** Whether a view can be renamed, deleted or overwritten. Others can still be applied and duplicated. */\n canEdit?: (view: SavedView<TSettings>) => boolean;\n /** Whether new views can be saved here (save as new view, duplicate). Defaults to true. */\n canCreate?: boolean;\n 'aria-label'?: string;\n className?: string;\n};\n\ntype PickerItem = { value: string; label: string; viewId: string | undefined };\n\nconst DEFAULT_ITEM_VALUE = '';\n\n/**\n * A compact saved-views control for a page header: a searchable view picker, the active view's\n * actions, and save / reset once the page differs from the view. Driven by the same controller\n * as `SavedViewTabs`.\n */\nexport function SavedViewPicker<TSettings>({\n views,\n defaultLabel,\n newViewSettings,\n describeView,\n canEdit = () => true,\n canCreate = true,\n 'aria-label': ariaLabel = 'Views',\n className,\n}: SavedViewPickerProps<TSettings>) {\n const anchorRef = useRef<HTMLDivElement>(null);\n const [renaming, setRenaming] = useState(false);\n const { draft, activeView } = views;\n const creating = draft !== undefined && draft.viewId === undefined;\n const activeUnsaved = !creating && draft?.viewId !== undefined && views.unsaved;\n const editable = activeView !== undefined && canEdit(activeView);\n\n const items: PickerItem[] = [\n { value: DEFAULT_ITEM_VALUE, label: defaultLabel, viewId: undefined },\n ...views.views.map(view => ({ value: view.id, label: view.name, viewId: view.id })),\n ];\n const selected = items.find(item => item.viewId === activeView?.id) ?? items[0];\n const viewsById = new Map(views.views.map(view => [view.id, view]));\n\n return (\n <div\n role=\"group\"\n aria-label={ariaLabel}\n className={cn('flex min-w-0 flex-wrap items-center justify-end gap-1.5', className)}\n >\n {views.error && !creating && !renaming && (\n <Txt role=\"alert\" variant=\"caption\" className=\"min-w-0 truncate text-destructive-foreground\">\n {views.error}\n </Txt>\n )}\n {activeUnsaved && (\n <div className=\"flex shrink-0 items-center gap-1.5\">\n <Button type=\"button\" variant=\"ghost\" size=\"sm\" disabled={views.pending} onClick={views.discard}>\n Reset\n </Button>\n {editable && (\n <Button type=\"button\" variant=\"default\" size=\"sm\" disabled={views.pending} onClick={views.save}>\n Save changes\n </Button>\n )}\n </div>\n )}\n <div ref={anchorRef} className=\"flex min-w-0 items-center gap-0.5\">\n <ComboboxRoot\n items={items}\n value={selected}\n onValueChange={(item: PickerItem | null) => {\n if (item) views.select(item.viewId);\n }}\n isItemEqualToValue={(item: PickerItem, value: PickerItem) => item.value === value.value}\n autoHighlight\n >\n <ComboboxTrigger\n size=\"sm\"\n icon={<LayersIcon />}\n aria-label={`View: ${selected?.label}${activeUnsaved ? ', unsaved changes' : ''}`}\n className=\"max-w-60\"\n >\n {selected?.label}\n {activeUnsaved && (\n <span className=\"ml-1.5 inline-block size-1.5 rounded-full bg-warning-indicator align-middle\" />\n )}\n </ComboboxTrigger>\n <ComboboxContent align=\"end\">\n <ComboboxSearch placeholder=\"Search views…\" />\n <ComboboxEmpty>No views found.</ComboboxEmpty>\n <ComboboxList>\n {(item: PickerItem) => {\n const view = item.viewId ? viewsById.get(item.viewId) : undefined;\n return (\n <ComboboxItem key={item.value} value={item}>\n <span className=\"truncate\">{item.label}</span>\n {view && describeView && <ComboboxItemEnd>{describeView(view)}</ComboboxItemEnd>}\n </ComboboxItem>\n );\n }}\n </ComboboxList>\n </ComboboxContent>\n </ComboboxRoot>\n {activeView && !creating && (editable || canCreate) && (\n <DropdownMenu>\n <DropdownMenu.Trigger variant=\"ghost\" size=\"icon-sm\" tooltip=\"View actions\" className=\"shrink-0\">\n <EllipsisIcon />\n </DropdownMenu.Trigger>\n <DropdownMenu.Content align=\"end\">\n {editable && (\n <DropdownMenu.Item onClick={() => setRenaming(true)}>\n <TextCursorInputIcon aria-hidden />\n Rename\n </DropdownMenu.Item>\n )}\n {canCreate && (\n <DropdownMenu.Item onClick={() => views.duplicate(activeView.id)}>\n <CopyIcon aria-hidden />\n Duplicate\n </DropdownMenu.Item>\n )}\n {editable && (\n <>\n <DropdownMenu.Separator />\n <DropdownMenu.Item variant=\"destructive\" onClick={() => views.remove(activeView.id)}>\n <Trash2Icon aria-hidden />\n Delete view\n </DropdownMenu.Item>\n </>\n )}\n </DropdownMenu.Content>\n </DropdownMenu>\n )}\n </div>\n {canCreate && (\n <Popover\n open={creating}\n onOpenChange={open => {\n if (open) views.create(newViewSettings);\n else views.discard();\n }}\n >\n <PopoverTrigger variant=\"ghost\" size=\"icon-sm\" tooltip=\"Save as new view\" className=\"shrink-0\">\n <LayersPlusIcon />\n </PopoverTrigger>\n <PopoverContent align=\"end\" className=\"w-72\">\n {creating && (\n <ViewNameForm\n title=\"Save as new view\"\n initialName={draft.name}\n submitLabel=\"Save view\"\n error={views.error}\n pending={views.pending}\n onNameChange={name => views.change({ name })}\n onSubmit={() => views.save()}\n onCancel={views.discard}\n />\n )}\n </PopoverContent>\n </Popover>\n )}\n {activeView && (\n <RenamePopover\n open={renaming}\n anchorRef={anchorRef}\n name={activeView.name}\n error={views.error}\n pending={views.pending}\n onClose={() => setRenaming(false)}\n onRename={name => views.rename(activeView.id, name)}\n />\n )}\n </div>\n );\n}\n\nfunction RenamePopover({\n open,\n anchorRef,\n name,\n error,\n pending,\n onClose,\n onRename,\n}: {\n open: boolean;\n anchorRef: RefObject<HTMLDivElement | null>;\n name: string;\n error: string | undefined;\n pending: boolean | undefined;\n onClose: () => void;\n onRename: (name: string) => boolean | Promise<boolean>;\n}) {\n // The name that last failed to save: its error shows until the user types something else.\n const [failedName, setFailedName] = useState<string>();\n const [typedName, setTypedName] = useState(name);\n const close = () => {\n setFailedName(undefined);\n setTypedName(name);\n onClose();\n };\n return (\n <Popover open={open} onOpenChange={next => !next && close()}>\n <PopoverContent anchor={anchorRef} align=\"end\" className=\"w-72\">\n {open && (\n <ViewNameForm\n title=\"Rename view\"\n initialName={name}\n submitLabel=\"Rename\"\n error={failedName !== undefined && failedName === typedName ? error : undefined}\n pending={pending}\n onNameChange={setTypedName}\n onSubmit={async next => {\n if (await onRename(next)) close();\n else setFailedName(next);\n }}\n onCancel={close}\n />\n )}\n </PopoverContent>\n </Popover>\n );\n}\n\nfunction ViewNameForm({\n title,\n initialName,\n submitLabel,\n error,\n pending,\n onNameChange,\n onSubmit,\n onCancel,\n}: {\n title: string;\n initialName: string;\n submitLabel: string;\n error?: string;\n pending?: boolean;\n onNameChange?: (name: string) => void;\n onSubmit: (name: string) => void | Promise<void>;\n onCancel: () => void;\n}) {\n const [name, setName] = useState(initialName);\n const submit = (event: FormEvent) => {\n event.preventDefault();\n if (name.trim()) void onSubmit(name);\n };\n return (\n <form className=\"flex flex-col gap-3\" onSubmit={submit}>\n <Txt as=\"h2\" variant=\"label\">\n {title}\n </Txt>\n <Field invalid={error !== undefined}>\n <Input\n aria-label=\"View name\"\n size=\"sm\"\n autoFocus\n onFocus={event => event.currentTarget.select()}\n maxLength={MAX_SAVED_VIEW_NAME_CHARS}\n value={name}\n onChange={event => {\n setName(event.target.value);\n onNameChange?.(event.target.value);\n }}\n />\n <FieldError>{error}</FieldError>\n </Field>\n <div className=\"flex justify-end gap-1.5\">\n <Button type=\"button\" variant=\"ghost\" size=\"sm\" onClick={onCancel}>\n Cancel\n </Button>\n <Button type=\"submit\" variant=\"default\" size=\"sm\" disabled={pending || !name.trim()}>\n {submitLabel}\n </Button>\n </div>\n </form>\n );\n}\n","import type { SavedViewPage } from '@mastra/core/storage';\nimport { createPortal } from 'react-dom';\nimport { useSavedViewsSource } from './saved-views-source';\nimport type { SavedViewsContextValue } from './saved-views-source';\nimport { useHostedSavedViews } from './use-hosted-saved-views';\nimport type { SavedViewColumnsControl } from './use-hosted-saved-views';\nimport { useObservabilityHeaderSlot } from '@/domains/observability/components/observability-header-slot';\nimport { SavedViewPicker } from '@/ds/components/SavedViews/saved-view-picker';\nimport type { SetURLSearchParamsLike } from '@/lib/sort/use-url-sort';\nimport { cn } from '@/lib/utils';\n\nconst DEFAULT_LABELS: Record<SavedViewPage, string> = {\n traces: 'All traces',\n spans: 'All spans',\n threads: 'All threads',\n logs: 'All logs',\n};\n\nexport type ObservabilitySavedViewsProps = {\n page: SavedViewPage;\n searchParams: URLSearchParams;\n setSearchParams: SetURLSearchParamsLike;\n /** The page's column picker (traces, spans, threads), so views save and restore columns. */\n columns?: SavedViewColumnsControl;\n /**\n * The range the page shows when the URL names none, when the host's differs from the page's own\n * (the same value passed to `useObservabilityListFilters`).\n */\n defaultDatePreset?: string;\n className?: string;\n};\n\n/**\n * The saved views of an observability page: a searchable view picker with save and reset actions.\n * Inside the shared traces / spans / threads header it moves into that header's row. Renders nothing\n * unless a `SavedViewsProvider` above it supplies where views are stored.\n */\nexport function ObservabilitySavedViews(props: ObservabilitySavedViewsProps) {\n const context = useSavedViewsSource();\n if (!context) return null;\n return <HostedSavedViewsBar {...props} {...context} />;\n}\n\nfunction HostedSavedViewsBar({\n page,\n searchParams,\n setSearchParams,\n columns,\n defaultDatePreset,\n className,\n source,\n queryKeyScope,\n canEdit,\n canCreate = true,\n}: ObservabilitySavedViewsProps & SavedViewsContextValue) {\n const headerSlot = useObservabilityHeaderSlot();\n const views = useHostedSavedViews({\n page,\n source,\n queryKeyScope,\n canEdit,\n canCreate,\n searchParams,\n setSearchParams,\n columns,\n defaultDatePreset,\n });\n\n const picker = (\n <SavedViewPicker\n views={views}\n defaultLabel={DEFAULT_LABELS[page]}\n aria-label=\"Saved views\"\n newViewSettings={{ state: { schemaVersion: 1, page, filters: [] } }}\n describeView={view => (view.settings.record?.scope === 'org' ? 'Shared' : undefined)}\n canEdit={view => !canEdit || !view.settings.record || canEdit(view.settings.record)}\n canCreate={canCreate}\n className={className}\n />\n );\n return headerSlot ? createPortal(picker, headerSlot) : picker;\n}\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"observability-saved-views-BBam8Fr5.js","names":["_Fragment"],"sources":["../src/ds/components/SavedViews/saved-view-picker.tsx","../src/domains/observability/saved-views/observability-saved-views.tsx"],"sourcesContent":["import { CopyIcon, EllipsisIcon, LayersIcon, LayersPlusIcon, TextCursorInputIcon, Trash2Icon } from 'lucide-react';\nimport { useRef, useState } from 'react';\nimport type { FormEvent, ReactNode, RefObject } from 'react';\nimport { MAX_SAVED_VIEW_NAME_CHARS } from './saved-view-schema';\nimport type { SavedView } from './saved-view-schema';\nimport type { SavedViewsController } from './use-saved-views';\nimport { Button } from '@/ds/components/Button/Button';\nimport {\n ComboboxContent,\n ComboboxEmpty,\n ComboboxItem,\n ComboboxItemEnd,\n ComboboxList,\n ComboboxRoot,\n ComboboxSearch,\n ComboboxTrigger,\n} from '@/ds/components/Combobox/combobox-parts';\nimport { DropdownMenu } from '@/ds/components/DropdownMenu';\nimport { Field, FieldError } from '@/ds/components/Field';\nimport { Input } from '@/ds/components/Input/input';\nimport { Popover, PopoverContent, PopoverTrigger } from '@/ds/components/Popover';\nimport { Txt } from '@/ds/components/Txt';\nimport { cn } from '@/lib/utils';\n\nexport type SavedViewPickerProps<TSettings> = {\n views: SavedViewsController<TSettings>;\n /** Names the page's unfiltered state, e.g. \"All traces\". */\n defaultLabel: string;\n newViewSettings: NoInfer<TSettings>;\n /** Muted text after a view in the list, e.g. \"Shared\". */\n describeView?: (view: SavedView<TSettings>) => ReactNode;\n /** Whether a view can be renamed, deleted or overwritten. Others can still be applied and duplicated. */\n canEdit?: (view: SavedView<TSettings>) => boolean;\n /** Whether new views can be saved here (save as new view, duplicate). Defaults to true. */\n canCreate?: boolean;\n 'aria-label'?: string;\n className?: string;\n};\n\ntype PickerItem = { value: string; label: string; viewId: string | undefined };\n\nconst DEFAULT_ITEM_VALUE = '';\n\n/**\n * A compact saved-views control for a page header: a searchable view picker, the active view's\n * actions, and save / reset once the page differs from the view. Driven by the same controller\n * as `SavedViewTabs`.\n */\nexport function SavedViewPicker<TSettings>({\n views,\n defaultLabel,\n newViewSettings,\n describeView,\n canEdit = () => true,\n canCreate = true,\n 'aria-label': ariaLabel = 'Views',\n className,\n}: SavedViewPickerProps<TSettings>) {\n const anchorRef = useRef<HTMLDivElement>(null);\n const [renaming, setRenaming] = useState(false);\n const { draft, activeView } = views;\n const creating = draft !== undefined && draft.viewId === undefined;\n const activeUnsaved = !creating && draft?.viewId !== undefined && views.unsaved;\n const editable = activeView !== undefined && canEdit(activeView);\n\n const items: PickerItem[] = [\n { value: DEFAULT_ITEM_VALUE, label: defaultLabel, viewId: undefined },\n ...views.views.map(view => ({ value: view.id, label: view.name, viewId: view.id })),\n ];\n const selected = items.find(item => item.viewId === activeView?.id) ?? items[0];\n const viewsById = new Map(views.views.map(view => [view.id, view]));\n\n return (\n <div\n role=\"group\"\n aria-label={ariaLabel}\n className={cn('flex min-w-0 flex-wrap items-center justify-end gap-1.5', className)}\n >\n {views.error && !creating && !renaming && (\n <Txt role=\"alert\" variant=\"caption\" className=\"min-w-0 truncate text-destructive-foreground\">\n {views.error}\n </Txt>\n )}\n {activeUnsaved && (\n <div className=\"flex shrink-0 items-center gap-1.5\">\n <Button type=\"button\" variant=\"ghost\" size=\"sm\" disabled={views.pending} onClick={views.discard}>\n Reset\n </Button>\n {editable && (\n <Button type=\"button\" variant=\"default\" size=\"sm\" disabled={views.pending} onClick={views.save}>\n Save changes\n </Button>\n )}\n </div>\n )}\n <div ref={anchorRef} className=\"flex min-w-0 items-center gap-0.5\">\n <ComboboxRoot\n items={items}\n value={selected}\n onValueChange={(item: PickerItem | null) => {\n if (item) views.select(item.viewId);\n }}\n isItemEqualToValue={(item: PickerItem, value: PickerItem) => item.value === value.value}\n autoHighlight\n >\n <ComboboxTrigger\n size=\"sm\"\n icon={<LayersIcon />}\n aria-label={`View: ${selected?.label}${activeUnsaved ? ', unsaved changes' : ''}`}\n className=\"max-w-60\"\n >\n {selected?.label}\n {activeUnsaved && (\n <span className=\"ml-1.5 inline-block size-1.5 rounded-full bg-warning-indicator align-middle\" />\n )}\n </ComboboxTrigger>\n <ComboboxContent align=\"end\">\n <ComboboxSearch placeholder=\"Search views…\" />\n <ComboboxEmpty>No views found.</ComboboxEmpty>\n <ComboboxList>\n {(item: PickerItem) => {\n const view = item.viewId ? viewsById.get(item.viewId) : undefined;\n return (\n <ComboboxItem key={item.value} value={item}>\n <span className=\"truncate\">{item.label}</span>\n {view && describeView && <ComboboxItemEnd>{describeView(view)}</ComboboxItemEnd>}\n </ComboboxItem>\n );\n }}\n </ComboboxList>\n </ComboboxContent>\n </ComboboxRoot>\n {activeView && !creating && (editable || canCreate) && (\n <DropdownMenu>\n <DropdownMenu.Trigger variant=\"ghost\" size=\"icon-sm\" tooltip=\"View actions\" className=\"shrink-0\">\n <EllipsisIcon />\n </DropdownMenu.Trigger>\n <DropdownMenu.Content align=\"end\">\n {editable && (\n <DropdownMenu.Item onClick={() => setRenaming(true)}>\n <TextCursorInputIcon aria-hidden />\n Rename\n </DropdownMenu.Item>\n )}\n {canCreate && (\n <DropdownMenu.Item onClick={() => views.duplicate(activeView.id)}>\n <CopyIcon aria-hidden />\n Duplicate\n </DropdownMenu.Item>\n )}\n {editable && (\n <>\n <DropdownMenu.Separator />\n <DropdownMenu.Item variant=\"destructive\" onClick={() => views.remove(activeView.id)}>\n <Trash2Icon aria-hidden />\n Delete view\n </DropdownMenu.Item>\n </>\n )}\n </DropdownMenu.Content>\n </DropdownMenu>\n )}\n </div>\n {canCreate && (\n <Popover\n open={creating}\n onOpenChange={open => {\n if (open) views.create(newViewSettings);\n else views.discard();\n }}\n >\n <PopoverTrigger variant=\"ghost\" size=\"icon-sm\" tooltip=\"Save as new view\" className=\"shrink-0\">\n <LayersPlusIcon />\n </PopoverTrigger>\n <PopoverContent align=\"end\" className=\"w-72\">\n {creating && (\n <ViewNameForm\n title=\"Save as new view\"\n initialName={draft.name}\n submitLabel=\"Save view\"\n error={views.error}\n pending={views.pending}\n onNameChange={name => views.change({ name })}\n onSubmit={() => views.save()}\n onCancel={views.discard}\n />\n )}\n </PopoverContent>\n </Popover>\n )}\n {activeView && (\n <RenamePopover\n open={renaming}\n anchorRef={anchorRef}\n name={activeView.name}\n error={views.error}\n pending={views.pending}\n onClose={() => setRenaming(false)}\n onRename={name => views.rename(activeView.id, name)}\n />\n )}\n </div>\n );\n}\n\nfunction RenamePopover({\n open,\n anchorRef,\n name,\n error,\n pending,\n onClose,\n onRename,\n}: {\n open: boolean;\n anchorRef: RefObject<HTMLDivElement | null>;\n name: string;\n error: string | undefined;\n pending: boolean | undefined;\n onClose: () => void;\n onRename: (name: string) => boolean | Promise<boolean>;\n}) {\n // The name that last failed to save: its error shows until the user types something else.\n const [failedName, setFailedName] = useState<string>();\n const [typedName, setTypedName] = useState(name);\n const close = () => {\n setFailedName(undefined);\n setTypedName(name);\n onClose();\n };\n return (\n <Popover open={open} onOpenChange={next => !next && close()}>\n <PopoverContent anchor={anchorRef} align=\"end\" className=\"w-72\">\n {open && (\n <ViewNameForm\n title=\"Rename view\"\n initialName={name}\n submitLabel=\"Rename\"\n error={failedName !== undefined && failedName === typedName ? error : undefined}\n pending={pending}\n onNameChange={setTypedName}\n onSubmit={async next => {\n if (await onRename(next)) close();\n else setFailedName(next);\n }}\n onCancel={close}\n />\n )}\n </PopoverContent>\n </Popover>\n );\n}\n\nfunction ViewNameForm({\n title,\n initialName,\n submitLabel,\n error,\n pending,\n onNameChange,\n onSubmit,\n onCancel,\n}: {\n title: string;\n initialName: string;\n submitLabel: string;\n error?: string;\n pending?: boolean;\n onNameChange?: (name: string) => void;\n onSubmit: (name: string) => void | Promise<void>;\n onCancel: () => void;\n}) {\n const [name, setName] = useState(initialName);\n const submit = (event: FormEvent) => {\n event.preventDefault();\n if (name.trim()) void onSubmit(name);\n };\n return (\n <form className=\"flex flex-col gap-3\" onSubmit={submit}>\n <Txt as=\"h2\" variant=\"label\">\n {title}\n </Txt>\n <Field invalid={error !== undefined}>\n <Input\n aria-label=\"View name\"\n size=\"sm\"\n autoFocus\n onFocus={event => event.currentTarget.select()}\n maxLength={MAX_SAVED_VIEW_NAME_CHARS}\n value={name}\n onChange={event => {\n setName(event.target.value);\n onNameChange?.(event.target.value);\n }}\n />\n <FieldError>{error}</FieldError>\n </Field>\n <div className=\"flex justify-end gap-1.5\">\n <Button type=\"button\" variant=\"ghost\" size=\"sm\" onClick={onCancel}>\n Cancel\n </Button>\n <Button type=\"submit\" variant=\"default\" size=\"sm\" disabled={pending || !name.trim()}>\n {submitLabel}\n </Button>\n </div>\n </form>\n );\n}\n","import type { SavedViewPage } from '@mastra/core/storage';\nimport { createPortal } from 'react-dom';\nimport { useSavedViewsSource } from './saved-views-source';\nimport type { SavedViewsContextValue } from './saved-views-source';\nimport { useHostedSavedViews } from './use-hosted-saved-views';\nimport type { SavedViewColumnsControl } from './use-hosted-saved-views';\nimport { useObservabilityHeaderSlot } from '@/domains/observability/components/observability-header-slot';\nimport { SavedViewPicker } from '@/ds/components/SavedViews/saved-view-picker';\nimport type { SetURLSearchParamsLike } from '@/lib/sort/use-url-sort';\nimport { cn } from '@/lib/utils';\n\nconst DEFAULT_LABELS: Record<SavedViewPage, string> = {\n traces: 'All traces',\n spans: 'All spans',\n threads: 'All threads',\n logs: 'All logs',\n};\n\nexport type ObservabilitySavedViewsProps = {\n page: SavedViewPage;\n searchParams: URLSearchParams;\n setSearchParams: SetURLSearchParamsLike;\n /** The page's column picker (traces, spans, threads), so views save and restore columns. */\n columns?: SavedViewColumnsControl;\n /**\n * The range the page shows when the URL names none, when the host's differs from the page's own\n * (the same value passed to `useObservabilityListFilters`).\n */\n defaultDatePreset?: string;\n className?: string;\n};\n\n/**\n * The saved views of an observability page: a searchable view picker with save and reset actions.\n * Inside the shared traces / spans / threads header it moves into that header's row. Renders nothing\n * unless a `SavedViewsProvider` above it supplies where views are stored.\n */\nexport function ObservabilitySavedViews(props: ObservabilitySavedViewsProps) {\n const context = useSavedViewsSource();\n if (!context) return null;\n return <HostedSavedViewsBar {...props} {...context} />;\n}\n\nfunction HostedSavedViewsBar({\n page,\n searchParams,\n setSearchParams,\n columns,\n defaultDatePreset,\n className,\n source,\n queryKeyScope,\n canEdit,\n canCreate = true,\n}: ObservabilitySavedViewsProps & SavedViewsContextValue) {\n const headerSlot = useObservabilityHeaderSlot();\n const views = useHostedSavedViews({\n page,\n source,\n queryKeyScope,\n canEdit,\n canCreate,\n searchParams,\n setSearchParams,\n columns,\n defaultDatePreset,\n });\n\n const picker = (\n <SavedViewPicker\n views={views}\n defaultLabel={DEFAULT_LABELS[page]}\n aria-label=\"Saved views\"\n newViewSettings={{ state: { schemaVersion: 1, page, filters: [] } }}\n describeView={view => (view.settings.record?.scope === 'org' ? 'Shared' : undefined)}\n canEdit={view => !canEdit || !view.settings.record || canEdit(view.settings.record)}\n canCreate={canCreate}\n className={className}\n />\n );\n return headerSlot ? createPortal(picker, headerSlot) : picker;\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAyCA,IAAM,qBAAqB;;;;;;AAO3B,SAAgB,gBAA2B,EACzC,OACA,cACA,iBACA,cACA,gBAAgB,MAChB,YAAY,MACZ,cAAc,YAAY,SAC1B,aACkC;CAClC,MAAM,YAAY,OAAuB,IAAI;CAC7C,MAAM,CAAC,UAAU,eAAe,SAAS,KAAK;CAC9C,MAAM,EAAE,OAAO,eAAe;CAC9B,MAAM,WAAW,UAAU,KAAA,KAAa,MAAM,WAAW,KAAA;CACzD,MAAM,gBAAgB,CAAC,YAAY,OAAO,WAAW,KAAA,KAAa,MAAM;CACxE,MAAM,WAAW,eAAe,KAAA,KAAa,QAAQ,UAAU;CAE/D,MAAM,QAAsB,CAC1B;EAAE,OAAO;EAAoB,OAAO;EAAc,QAAQ,KAAA;CAAU,GACpE,GAAG,MAAM,MAAM,KAAI,UAAS;EAAE,OAAO,KAAK;EAAI,OAAO,KAAK;EAAM,QAAQ,KAAK;CAAG,EAAE,CACpF;CACA,MAAM,WAAW,MAAM,MAAK,SAAQ,KAAK,WAAW,YAAY,EAAE,KAAK,MAAM;CAC7E,MAAM,YAAY,IAAI,IAAI,MAAM,MAAM,KAAI,SAAQ,CAAC,KAAK,IAAI,IAAI,CAAC,CAAC;CAElE,OACE,qBAAC,OAAD;EACE,MAAK;EACL,cAAY;EACZ,WAAW,GAAG,2DAA2D,SAAS;EAHpF,UAAA;GAKG,MAAM,SAAS,CAAC,YAAY,CAAC,YAC5B,oBAAC,KAAD;IAAK,MAAK;IAAQ,SAAQ;IAAU,WAAU;IAC3C,UAAA,MAAM;GACJ,CAAA;GAEN,iBACC,qBAAC,OAAD;IAAK,WAAU;IAAf,UAAA,CACE,oBAAC,QAAD;KAAQ,MAAK;KAAS,SAAQ;KAAQ,MAAK;KAAK,UAAU,MAAM;KAAS,SAAS,MAAM;KAAS,UAAA;IAEzF,CAAA,GACP,YACC,oBAAC,QAAD;KAAQ,MAAK;KAAS,SAAQ;KAAU,MAAK;KAAK,UAAU,MAAM;KAAS,SAAS,MAAM;KAAM,UAAA;IAExF,CAAA,CAEP;;GAEP,qBAAC,OAAD;IAAK,KAAK;IAAW,WAAU;IAA/B,UAAA,CACE,qBAAC,cAAD;KACS;KACP,OAAO;KACP,gBAAgB,SAA4B;MAC1C,IAAI,MAAM,MAAM,OAAO,KAAK,MAAM;KACpC;KACA,qBAAqB,MAAkB,UAAsB,KAAK,UAAU,MAAM;KAClF,eAAA;KAPF,UAAA,CASE,qBAAC,iBAAD;MACE,MAAK;MACL,MAAM,oBAAC,YAAD,CAAa,CAAA;MACnB,cAAY,SAAS,UAAU,QAAQ,gBAAgB,sBAAsB;MAC7E,WAAU;MAJZ,UAAA,CAMG,UAAU,OACV,iBACC,oBAAC,QAAD,EAAM,WAAU,8EAA+E,CAAA,CAElF;KACjB,CAAA,GAAA,qBAAC,iBAAD;MAAiB,OAAM;MAAvB,UAAA;OACE,oBAAC,gBAAD,EAAgB,aAAY,gBAAiB,CAAA;OAC7C,oBAAC,eAAD,EAAA,UAAe,kBAA8B,CAAA;OAC7C,oBAAC,cAAD,EAAA,WACI,SAAqB;QACrB,MAAM,OAAO,KAAK,SAAS,UAAU,IAAI,KAAK,MAAM,IAAI,KAAA;QACxD,OACE,qBAAC,cAAD;SAA+B,OAAO;SAAtC,UAAA,CACE,oBAAC,QAAD;UAAM,WAAU;UAAY,UAAA,KAAK;SAAY,CAAA,GAC5C,QAAQ,gBAAgB,oBAAC,iBAAD,EAAA,UAAkB,aAAa,IAAI,EAAmB,CAAA,CACnE;QAHK,GAAA,KAAK,KAGV;OAElB,EACY,CAAA;MACC;KACL,CAAA,CAAA;IACb,CAAA,GAAA,cAAc,CAAC,aAAa,YAAY,cACvC,qBAAC,cAAD,EAAA,UAAA,CACE,oBAAC,aAAa,SAAd;KAAsB,SAAQ;KAAQ,MAAK;KAAU,SAAQ;KAAe,WAAU;KACpF,UAAA,oBAAC,cAAD,CAAe,CAAA;IACK,CAAA,GACtB,qBAAC,aAAa,SAAd;KAAsB,OAAM;KAA5B,UAAA;MACG,YACC,qBAAC,aAAa,MAAd;OAAmB,eAAe,YAAY,IAAI;OAAlD,UAAA,CACE,oBAAC,qBAAD,EAAqB,eAAA,KAAa,CAAA,GAAC,QAElB;;MAEpB,aACC,qBAAC,aAAa,MAAd;OAAmB,eAAe,MAAM,UAAU,WAAW,EAAE;OAA/D,UAAA,CACE,oBAAC,UAAD,EAAU,eAAA,KAAa,CAAA,GAAC,WAEP;;MAEpB,YACC,qBAAAA,YAAA,EAAA,UAAA,CACE,oBAAC,aAAa,WAAd,CAAyB,CAAA,GACzB,qBAAC,aAAa,MAAd;OAAmB,SAAQ;OAAc,eAAe,MAAM,OAAO,WAAW,EAAE;OAAlF,UAAA,CACE,oBAAC,YAAD,EAAY,eAAA,KAAa,CAAA,GAAC,aAET;MACnB,CAAA,CAAA,EAAA,CAAA;KAEgB;IACV,CAAA,CAAA,EAAA,CAAA,CAEb;;GACJ,aACC,qBAAC,SAAD;IACE,MAAM;IACN,eAAc,SAAQ;KACpB,IAAI,MAAM,MAAM,OAAO,eAAe;UACjC,MAAM,QAAQ;IACrB;IALF,UAAA,CAOE,oBAAC,gBAAD;KAAgB,SAAQ;KAAQ,MAAK;KAAU,SAAQ;KAAmB,WAAU;KAClF,UAAA,oBAAC,gBAAD,CAAiB,CAAA;IACH,CAAA,GAChB,oBAAC,gBAAD;KAAgB,OAAM;KAAM,WAAU;KACnC,UAAA,YACC,oBAAC,cAAD;MACE,OAAM;MACN,aAAa,MAAM;MACnB,aAAY;MACZ,OAAO,MAAM;MACb,SAAS,MAAM;MACf,eAAc,SAAQ,MAAM,OAAO,EAAE,KAAK,CAAC;MAC3C,gBAAgB,MAAM,KAAK;MAC3B,UAAU,MAAM;KACjB,CAAA;IAEW,CAAA,CACT;;GAEV,cACC,oBAAC,eAAD;IACE,MAAM;IACK;IACX,MAAM,WAAW;IACjB,OAAO,MAAM;IACb,SAAS,MAAM;IACf,eAAe,YAAY,KAAK;IAChC,WAAU,SAAQ,MAAM,OAAO,WAAW,IAAI,IAAI;GACnD,CAAA;EAEA;;AAET;AAEA,SAAS,cAAc,EACrB,MACA,WACA,MACA,OACA,SACA,SACA,YASC;CAED,MAAM,CAAC,YAAY,iBAAiB,SAAiB;CACrD,MAAM,CAAC,WAAW,gBAAgB,SAAS,IAAI;CAC/C,MAAM,cAAc;EAClB,cAAc,KAAA,CAAS;EACvB,aAAa,IAAI;EACjB,QAAQ;CACV;CACA,OACE,oBAAC,SAAD;EAAe;EAAM,eAAc,SAAQ,CAAC,QAAQ,MAAM;EACxD,UAAA,oBAAC,gBAAD;GAAgB,QAAQ;GAAW,OAAM;GAAM,WAAU;GACtD,UAAA,QACC,oBAAC,cAAD;IACE,OAAM;IACN,aAAa;IACb,aAAY;IACZ,OAAO,eAAe,KAAA,KAAa,eAAe,YAAY,QAAQ,KAAA;IAC7D;IACT,cAAc;IACd,UAAU,OAAM,SAAQ;KACtB,IAAI,MAAM,SAAS,IAAI,GAAG,MAAM;UAC3B,cAAc,IAAI;IACzB;IACA,UAAU;GACX,CAAA;EAEW,CAAA;CACT,CAAA;AAEb;AAEA,SAAS,aAAa,EACpB,OACA,aACA,aACA,OACA,SACA,cACA,UACA,YAUC;CACD,MAAM,CAAC,MAAM,WAAW,SAAS,WAAW;CAC5C,MAAM,UAAU,UAAqB;EACnC,MAAM,eAAe;EACrB,IAAI,KAAK,KAAK,GAAG,SAAc,IAAI;CACrC;CACA,OACE,qBAAC,QAAD;EAAM,WAAU;EAAsB,UAAU;EAAhD,UAAA;GACE,oBAAC,KAAD;IAAK,IAAG;IAAK,SAAQ;IAClB,UAAA;GACE,CAAA;GACL,qBAAC,OAAD;IAAO,SAAS,UAAU,KAAA;IAA1B,UAAA,CACE,oBAAC,OAAD;KACE,cAAW;KACX,MAAK;KACL,WAAA;KACA,UAAS,UAAS,MAAM,cAAc,OAAO;KAC7C,WAAA;KACA,OAAO;KACP,WAAU,UAAS;MACjB,QAAQ,MAAM,OAAO,KAAK;MAC1B,eAAe,MAAM,OAAO,KAAK;KACnC;IACD,CAAA,GACD,oBAAC,YAAD,EAAA,UAAa,MAAkB,CAAA,CAC1B;;GACP,qBAAC,OAAD;IAAK,WAAU;IAAf,UAAA,CACE,oBAAC,QAAD;KAAQ,MAAK;KAAS,SAAQ;KAAQ,MAAK;KAAK,SAAS;KAAU,UAAA;IAE3D,CAAA,GACR,oBAAC,QAAD;KAAQ,MAAK;KAAS,SAAQ;KAAU,MAAK;KAAK,UAAU,WAAW,CAAC,KAAK,KAAK;KAC/E,UAAA;IACK,CAAA,CACL;;EACD;;AAEV;;ACxSA,IAAM,iBAAgD;CACpD,QAAQ;CACR,OAAO;CACP,SAAS;CACT,MAAM;AACR;;;;;;AAqBA,SAAgB,wBAAwB,OAAqC;CAC3E,MAAM,UAAU,oBAAoB;CACpC,IAAI,CAAC,SAAS,OAAO;CACrB,OAAO,oBAAC,qBAAD;EAAqB,GAAI;EAAO,GAAI;CAAU,CAAA;AACvD;AAEA,SAAS,oBAAoB,EAC3B,MACA,cACA,iBACA,SACA,mBACA,WACA,QACA,eACA,SACA,YAAY,QAC4C;CACxD,MAAM,aAAa,2BAA2B;CAC9C,MAAM,QAAQ,oBAAoB;EAChC;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACF,CAAC;CAED,MAAM,SACJ,oBAAC,iBAAD;EACS;EACP,cAAc,eAAe;EAC7B,cAAW;EACX,iBAAiB,EAAE,OAAO;GAAE,eAAe;GAAG;GAAM,SAAS,CAAC;EAAE,EAAE;EAClE,eAAc,SAAS,KAAK,SAAS,QAAQ,UAAU,QAAQ,WAAW,KAAA;EAC1E,UAAS,SAAQ,CAAC,WAAW,CAAC,KAAK,SAAS,UAAU,QAAQ,KAAK,SAAS,MAAM;EACvE;EACA;CACZ,CAAA;CAEH,OAAO,aAAa,aAAa,QAAQ,UAAU,IAAI;AACzD"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"property-filter-applied-BCeRLcXb.cjs","names":["Button","XIcon","DropdownMenu","EllipsisVerticalIcon","SaveIcon","Trash2Icon","cn","menuItemButtonClass","menuItemCheckClass","CheckIcon","useState","useMemo","_Fragment","menuSearchClasses","SearchIcon","passwordManagerOptOutProps","menuEmptyClass","Spinner","TooltipProvider","Tooltip","TooltipTrigger","ButtonsGroup","ButtonsGroupText","LockIcon","TooltipContent","useState","useRef","Input","Button","XIcon","Popover","PopoverTrigger","PopoverContent"],"sources":["../src/ds/components/PropertyFilter/property-filter-actions.tsx","../src/ds/components/PropertyFilter/pick-multi-panel.tsx","../src/ds/components/PropertyFilter/property-filter-applied.tsx"],"sourcesContent":["import { EllipsisVerticalIcon, SaveIcon, Trash2Icon, XIcon } from 'lucide-react';\nimport { Button } from '@/ds/components/Button/Button';\nimport { DropdownMenu } from '@/ds/components/DropdownMenu/dropdown-menu';\n\nexport type PropertyFilterActionsProps = {\n disabled?: boolean;\n /** Neutralize each pill's value (keep pills, clear values). Shown as a button, not a menu item. */\n onClear?: () => void;\n /** Fully remove all active filters. Rendered as \"Remove all filters\" inside the overflow menu. */\n onRemoveAll?: () => void;\n /** Persist the current filter set (typically to localStorage) for later restoration. */\n onSave?: () => void;\n /** Drop a previously-saved filter set. Wire only when a saved set actually exists. */\n onRemoveSaved?: () => void;\n};\n\n/**\n * Shared action bar for filter-driven pages (traces, logs, …). Renders a\n * Clear button and an overflow menu with Remove all / Save / Remove saved actions.\n */\nexport function PropertyFilterActions({\n disabled,\n onClear,\n onRemoveAll,\n onSave,\n onRemoveSaved,\n}: PropertyFilterActionsProps) {\n const hasMenuItems = !!(onRemoveAll || onSave || onRemoveSaved);\n if (!onClear && !hasMenuItems) return null;\n\n return (\n <div className=\"flex items-center gap-2\">\n {onClear && (\n <Button disabled={disabled} size=\"md\" onClick={onClear} icon={<XIcon />}>\n Clear\n </Button>\n )}\n\n {hasMenuItems && (\n <DropdownMenu>\n <DropdownMenu.Trigger asChild>\n <Button disabled={disabled} size=\"icon-md\" aria-label=\"More filter actions\">\n <EllipsisVerticalIcon />\n </Button>\n </DropdownMenu.Trigger>\n <DropdownMenu.Content align=\"end\">\n {onRemoveAll && (\n <DropdownMenu.Item onSelect={() => onRemoveAll()}>\n <XIcon />\n Remove all filters\n </DropdownMenu.Item>\n )}\n {onRemoveAll && (onSave || onRemoveSaved) && <DropdownMenu.Separator />}\n {onSave && (\n <DropdownMenu.Item onSelect={() => onSave()}>\n <SaveIcon />\n Save filters for next time\n </DropdownMenu.Item>\n )}\n {onRemoveSaved && (\n <DropdownMenu.Item onSelect={() => onRemoveSaved()}>\n <Trash2Icon />\n Remove saved filters\n </DropdownMenu.Item>\n )}\n </DropdownMenu.Content>\n </DropdownMenu>\n )}\n </div>\n );\n}\n","import { CheckIcon, SearchIcon } from 'lucide-react';\nimport { useMemo, useState } from 'react';\nimport type { PropertyFilterField, PropertyFilterToken } from './types';\nimport { Spinner } from '@/ds/components/Spinner/spinner';\nimport { menuEmptyClass, menuItemButtonClass, menuItemCheckClass, menuSearchClasses } from '@/ds/primitives/menu-item';\nimport { passwordManagerOptOutProps } from '@/ds/primitives/password-manager-autofill';\nimport { cn } from '@/lib/utils';\n\n// Same rendering as Combobox items: no visible control, a trailing check when selected.\n// Focus is on the item itself (roving via [data-pick-multi-item]).\nconst pickMultiItemClass = cn(menuItemButtonClass, 'min-w-0');\n\nfunction PickMultiItem({\n role,\n checked,\n label,\n onClick,\n}: {\n role: 'checkbox' | 'radio';\n checked: boolean;\n label: string;\n onClick: () => void;\n}) {\n return (\n <button\n type=\"button\"\n role={role}\n aria-checked={checked}\n data-selected={checked || undefined}\n data-pick-multi-item=\"\"\n title={label}\n className={pickMultiItemClass}\n onClick={onClick}\n >\n <span className=\"min-w-0 flex-1 truncate\">{label}</span>\n {checked && (\n <span className={menuItemCheckClass}>\n <CheckIcon />\n </span>\n )}\n </button>\n );\n}\n\ntype PickMultiField = Extract<PropertyFilterField, { kind: 'pick-multi' }>;\n\nexport type PickMultiPanelProps = {\n field: PickMultiField;\n tokens: PropertyFilterToken[];\n /** Always carries a value: an empty list is how the panel says \"nothing selected\". */\n onChange: (fieldId: string, value: string | string[]) => void;\n};\n\n/**\n * Reusable body for a pick-multi side popover: optional search input plus a\n * radio group (single-select) or checkbox list (when `field.multi` is true).\n * Shared between the Filter Creator's property-picker side popover and the\n * PropertyFilterApplied pill's inline editor so both surfaces use the exact same UI.\n */\nexport function PickMultiPanel({ field, tokens, onChange }: PickMultiPanelProps) {\n const [query, setQuery] = useState('');\n const listClassName = 'max-h-[80dvh] overflow-auto p-1';\n\n const filteredOptions = useMemo(() => {\n const q = query.trim().toLowerCase();\n if (!q) return field.options;\n return field.options.filter(o => o.label.toLowerCase().includes(q));\n }, [field.options, query]);\n\n const token = useMemo(() => tokens.find(t => t.fieldId === field.id), [tokens, field.id]);\n // Fall back to `defaultValue` when no token exists — lets view-toggle fields (e.g. List mode)\n // show their default option pre-selected before the user explicitly picks one.\n const selectedValue = typeof token?.value === 'string' ? token.value : !field.multi ? field.defaultValue : undefined;\n const selectedValues = useMemo<string[]>(() => {\n const value = token?.value;\n if (Array.isArray(value)) return value;\n if (typeof value === 'string') return [value];\n return [];\n }, [token]);\n\n return (\n <>\n {field.searchable !== false && (\n <div className={menuSearchClasses.container}>\n <SearchIcon className={menuSearchClasses.icon} />\n <input\n type=\"text\"\n value={query}\n onChange={e => setQuery(e.target.value)}\n placeholder={`Search ${field.label.toLowerCase()}...`}\n className={menuSearchClasses.input}\n {...passwordManagerOptOutProps}\n onKeyDown={e => {\n if (e.key !== 'ArrowDown') return;\n const panel = e.currentTarget.closest<HTMLElement>('[data-pick-multi-panel]');\n const first = panel?.querySelector<HTMLElement>('[data-pick-multi-item]:not([disabled])');\n if (!first) return;\n e.preventDefault();\n e.stopPropagation();\n first.focus();\n }}\n />\n </div>\n )}\n\n {field.isLoading ? (\n <div className={cn(menuEmptyClass, 'm-1')}>\n <Spinner size=\"sm\" className=\"size-3 text-muted-foreground\" />\n Loading options…\n </div>\n ) : filteredOptions.length === 0 ? (\n <div className={cn(menuEmptyClass, 'm-1')}>{field.emptyText ?? 'No option found.'}</div>\n ) : field.multi ? (\n <div className={listClassName}>\n <>\n {filteredOptions.map(option => {\n const checked = selectedValues.includes(option.value);\n return (\n <PickMultiItem\n key={option.value}\n role=\"checkbox\"\n checked={checked}\n label={option.label}\n onClick={() =>\n onChange(\n field.id,\n checked ? selectedValues.filter(v => v !== option.value) : [...selectedValues, option.value],\n )\n }\n />\n );\n })}\n </>\n </div>\n ) : (\n <div role=\"radiogroup\" className={listClassName}>\n <>\n {filteredOptions.map(option => (\n <PickMultiItem\n key={option.value}\n role=\"radio\"\n checked={selectedValue === option.value}\n label={option.label}\n onClick={() => onChange(field.id, option.value)}\n />\n ))}\n {!field.omitAnyOption && (\n <PickMultiItem\n role=\"radio\"\n checked={selectedValue === 'Any'}\n label=\"Any\"\n onClick={() => onChange(field.id, 'Any')}\n />\n )}\n </>\n </div>\n )}\n </>\n );\n}\n","import { LockIcon, XIcon } from 'lucide-react';\nimport type { ReactNode } from 'react';\nimport { useEffect, useRef, useState } from 'react';\nimport { Button } from '../Button';\nimport { ButtonsGroup, ButtonsGroupText } from '../ButtonsGroup';\nimport { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '../Tooltip';\nimport { PickMultiPanel } from './pick-multi-panel';\nimport type { PropertyFilterField, PropertyFilterToken } from './types';\nimport { Input } from '@/ds/components/Input';\nimport { Popover, PopoverContent, PopoverTrigger } from '@/ds/components/Popover/popover';\nimport { MENU_SIDE_OFFSET } from '@/ds/primitives/menu-item';\n\nexport type PropertyFilterAppliedProps = {\n fields: PropertyFilterField[];\n tokens: PropertyFilterToken[];\n onTokensChange: (tokens: PropertyFilterToken[]) => void;\n disabled?: boolean;\n /**\n * Field id that was just added via the Creator — rendered pill auto-focuses\n * its input so the user can start typing immediately.\n */\n autoFocusFieldId?: string;\n /**\n * Field ids whose pills must remain visible and read-only — value stays\n * displayed but cannot be edited or removed. Use when an upstream context\n * (e.g. agent-scoped traces tab) pre-applies a filter that the user must\n * not be able to clear.\n */\n lockedFieldIds?: readonly string[];\n /** Tooltip content shown on hover/focus of any locked pill. */\n lockedTooltipContent?: ReactNode;\n};\n\nfunction stringifyTokenValue(value: string | string[]) {\n if (Array.isArray(value)) return value.length === 0 ? 'Any' : value.join(', ');\n return value;\n}\n\nconst DEFAULT_LOCKED_TOOLTIP = 'This filter is set by the current context and cannot be removed here.';\n\nfunction lookupOptionLabel(field: PropertyFilterField, value: string | string[]): string {\n if (field.kind === 'pick-multi' && field.options) {\n if (Array.isArray(value)) {\n if (value.length === 0) return 'Any';\n return value.map(v => field.options.find(o => o.value === v)?.label ?? v).join(', ');\n }\n return field.options.find(o => o.value === value)?.label ?? value;\n }\n return stringifyTokenValue(value);\n}\n\ntype LockedTokenPillProps = {\n field: PropertyFilterField;\n value: string | string[];\n tooltipContent: ReactNode;\n};\n\nfunction LockedTokenPill({ field, value, tooltipContent }: LockedTokenPillProps) {\n const display = lookupOptionLabel(field, value);\n const lockA11yLabel = `${field.label} filter is locked by context`;\n\n return (\n <TooltipProvider delayDuration={150}>\n <Tooltip>\n <TooltipTrigger asChild>\n <ButtonsGroup\n data-locked-field-id={field.id}\n data-property-filter-pill=\"locked\"\n tabIndex={0}\n aria-label={lockA11yLabel}\n >\n <ButtonsGroupText>{field.label}</ButtonsGroupText>\n <ButtonsGroupText>is</ButtonsGroupText>\n <ButtonsGroupText>{display}</ButtonsGroupText>\n <ButtonsGroupText>\n <LockIcon />\n </ButtonsGroupText>\n </ButtonsGroup>\n </TooltipTrigger>\n <TooltipContent>{tooltipContent}</TooltipContent>\n </Tooltip>\n </TooltipProvider>\n );\n}\n\ntype TextTokenPillProps = {\n field: Extract<PropertyFilterField, { kind: 'text' }>;\n value: string;\n onChange: (value: string) => void;\n onRemove: () => void;\n disabled?: boolean;\n autoFocus?: boolean;\n};\n\nfunction TextTokenPill({ field, value, onChange, onRemove, disabled, autoFocus }: TextTokenPillProps) {\n // Local draft keeps the caret stable when the URL round-trip trims the\n // stored value (e.g. trailing spaces). We only re-sync from the prop when\n // the external value is genuinely different from our current (trimmed) draft.\n const [draft, setDraft] = useState(value);\n const inputRef = useRef<HTMLInputElement>(null);\n\n useEffect(() => {\n if (draft.trim() !== value) setDraft(value);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [value]);\n\n useEffect(() => {\n if (autoFocus) inputRef.current?.focus();\n }, [autoFocus]);\n\n return (\n <ButtonsGroup>\n <ButtonsGroupText>{field.label}</ButtonsGroupText>\n <ButtonsGroupText>is</ButtonsGroupText>\n <Input\n ref={inputRef}\n disabled={disabled}\n value={draft}\n placeholder={field.placeholder ?? `Enter ${field.label}`}\n onChange={e => {\n const next = e.target.value;\n setDraft(next);\n // Apply live — URL and traces query update on every keystroke.\n // Empty values persist as empty-value tokens so the pill stays visible.\n if (next.trim() !== value) onChange(next);\n }}\n onKeyDown={e => {\n if (e.key === 'Enter') {\n e.preventDefault();\n const trimmed = draft.trim();\n if (trimmed !== value) onChange(trimmed);\n } else if (e.key === 'Escape') {\n e.preventDefault();\n setDraft(value);\n e.currentTarget.blur();\n }\n }}\n />\n <Button\n size=\"icon-md\"\n type=\"button\"\n disabled={disabled}\n aria-label={`Remove ${field.label} filter`}\n onMouseDown={e => e.preventDefault()}\n onClick={onRemove}\n >\n <XIcon />\n </Button>\n </ButtonsGroup>\n );\n}\n\ntype PickMultiTokenPillProps = {\n field: Extract<PropertyFilterField, { kind: 'pick-multi' }>;\n token: PropertyFilterToken;\n tokens: PropertyFilterToken[];\n onChange: (fieldId: string, value: string | string[]) => void;\n onRemove: () => void;\n disabled?: boolean;\n};\n\nfunction PickMultiTokenPill({ field, token, tokens, onChange, onRemove, disabled }: PickMultiTokenPillProps) {\n const [open, setOpen] = useState(false);\n\n return (\n <ButtonsGroup>\n <ButtonsGroupText>{field.label}</ButtonsGroupText>\n <ButtonsGroupText>is</ButtonsGroupText>\n <Popover open={open} onOpenChange={setOpen}>\n <PopoverTrigger asChild>\n <Button type=\"button\" disabled={disabled}>\n {stringifyTokenValue(token.value)}\n </Button>\n </PopoverTrigger>\n <PopoverContent align=\"start\" sideOffset={MENU_SIDE_OFFSET} className=\"w-64 p-0\" data-pick-multi-panel>\n <PickMultiPanel field={field} tokens={tokens} onChange={onChange} />\n </PopoverContent>\n </Popover>\n <Button\n size=\"icon-md\"\n type=\"button\"\n disabled={disabled}\n aria-label={`Remove ${field.label} filter`}\n onClick={onRemove}\n >\n <XIcon />\n </Button>\n </ButtonsGroup>\n );\n}\n\n/**\n * Applied filter pills. Text/id-style tokens render with an always-active\n * input so the user can edit the value inline (and an empty token is valid —\n * it persists in the URL until the user explicitly removes it via ×).\n * Pick-multi tokens render with a clickable value that opens the same side\n * popover as the Filter Creator so the user can update selections in place.\n * Creation lives in a separate component (PropertyFilterCreator).\n */\nexport function PropertyFilterApplied({\n fields,\n tokens,\n onTokensChange,\n disabled,\n autoFocusFieldId,\n lockedFieldIds,\n lockedTooltipContent = DEFAULT_LOCKED_TOOLTIP,\n}: PropertyFilterAppliedProps) {\n if (tokens.length === 0) return null;\n\n const lockedSet = new Set(lockedFieldIds ?? []);\n\n const replaceTokenAt = (index: number, next: PropertyFilterToken) => {\n const copy = [...tokens];\n copy[index] = next;\n onTokensChange(copy);\n };\n\n const removeTokenAt = (index: number) => {\n onTokensChange(tokens.filter((_, i) => i !== index));\n };\n\n return (\n <div className=\"flex flex-wrap items-center gap-2\">\n {tokens.map((token, index) => {\n const field = fields.find(f => f.id === token.fieldId);\n if (!field) return null;\n\n if (lockedSet.has(token.fieldId)) {\n return (\n <LockedTokenPill\n key={`${token.fieldId}-${index}`}\n field={field}\n value={token.value}\n tooltipContent={lockedTooltipContent}\n />\n );\n }\n\n if (field.kind === 'text' && !Array.isArray(token.value)) {\n return (\n <TextTokenPill\n key={`${token.fieldId}-${index}`}\n field={field}\n value={token.value}\n disabled={disabled}\n autoFocus={autoFocusFieldId === token.fieldId}\n onChange={nextValue => replaceTokenAt(index, { fieldId: token.fieldId, value: nextValue })}\n onRemove={() => removeTokenAt(index)}\n />\n );\n }\n\n if (field.kind === 'pick-multi') {\n return (\n <PickMultiTokenPill\n key={`${token.fieldId}-${index}`}\n field={field}\n token={token}\n tokens={tokens}\n disabled={disabled}\n // Unselecting everything (empty array) keeps the pill alive in a\n // neutral state — the user explicitly removes it via ×. This lets\n // the page-level Reset neutralize values without dropping the pill.\n onChange={(fieldId, value) => replaceTokenAt(index, { fieldId, value })}\n onRemove={() => removeTokenAt(index)}\n />\n );\n }\n\n return (\n <ButtonsGroup key={`${token.fieldId}-${index}`}>\n <ButtonsGroupText>{field.label}</ButtonsGroupText>\n <ButtonsGroupText>is</ButtonsGroupText>\n <ButtonsGroupText>{stringifyTokenValue(token.value)}</ButtonsGroupText>\n <Button\n size=\"icon-md\"\n type=\"button\"\n disabled={disabled}\n aria-label={`Remove ${field.label} filter`}\n onClick={() => removeTokenAt(index)}\n >\n <XIcon />\n </Button>\n </ButtonsGroup>\n );\n })}\n </div>\n );\n}\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"property-filter-applied-p3dTTDdb.js","names":["_Fragment"],"sources":["../src/ds/components/PropertyFilter/property-filter-actions.tsx","../src/ds/components/PropertyFilter/pick-multi-panel.tsx","../src/ds/components/PropertyFilter/property-filter-applied.tsx"],"sourcesContent":["import { EllipsisVerticalIcon, SaveIcon, Trash2Icon, XIcon } from 'lucide-react';\nimport { Button } from '@/ds/components/Button/Button';\nimport { DropdownMenu } from '@/ds/components/DropdownMenu/dropdown-menu';\n\nexport type PropertyFilterActionsProps = {\n disabled?: boolean;\n /** Neutralize each pill's value (keep pills, clear values). Shown as a button, not a menu item. */\n onClear?: () => void;\n /** Fully remove all active filters. Rendered as \"Remove all filters\" inside the overflow menu. */\n onRemoveAll?: () => void;\n /** Persist the current filter set (typically to localStorage) for later restoration. */\n onSave?: () => void;\n /** Drop a previously-saved filter set. Wire only when a saved set actually exists. */\n onRemoveSaved?: () => void;\n};\n\n/**\n * Shared action bar for filter-driven pages (traces, logs, …). Renders a\n * Clear button and an overflow menu with Remove all / Save / Remove saved actions.\n */\nexport function PropertyFilterActions({\n disabled,\n onClear,\n onRemoveAll,\n onSave,\n onRemoveSaved,\n}: PropertyFilterActionsProps) {\n const hasMenuItems = !!(onRemoveAll || onSave || onRemoveSaved);\n if (!onClear && !hasMenuItems) return null;\n\n return (\n <div className=\"flex items-center gap-2\">\n {onClear && (\n <Button disabled={disabled} size=\"md\" onClick={onClear} icon={<XIcon />}>\n Clear\n </Button>\n )}\n\n {hasMenuItems && (\n <DropdownMenu>\n <DropdownMenu.Trigger asChild>\n <Button disabled={disabled} size=\"icon-md\" aria-label=\"More filter actions\">\n <EllipsisVerticalIcon />\n </Button>\n </DropdownMenu.Trigger>\n <DropdownMenu.Content align=\"end\">\n {onRemoveAll && (\n <DropdownMenu.Item onSelect={() => onRemoveAll()}>\n <XIcon />\n Remove all filters\n </DropdownMenu.Item>\n )}\n {onRemoveAll && (onSave || onRemoveSaved) && <DropdownMenu.Separator />}\n {onSave && (\n <DropdownMenu.Item onSelect={() => onSave()}>\n <SaveIcon />\n Save filters for next time\n </DropdownMenu.Item>\n )}\n {onRemoveSaved && (\n <DropdownMenu.Item onSelect={() => onRemoveSaved()}>\n <Trash2Icon />\n Remove saved filters\n </DropdownMenu.Item>\n )}\n </DropdownMenu.Content>\n </DropdownMenu>\n )}\n </div>\n );\n}\n","import { CheckIcon, SearchIcon } from 'lucide-react';\nimport { useMemo, useState } from 'react';\nimport type { PropertyFilterField, PropertyFilterToken } from './types';\nimport { Spinner } from '@/ds/components/Spinner/spinner';\nimport { menuEmptyClass, menuItemButtonClass, menuItemCheckClass, menuSearchClasses } from '@/ds/primitives/menu-item';\nimport { passwordManagerOptOutProps } from '@/ds/primitives/password-manager-autofill';\nimport { cn } from '@/lib/utils';\n\n// Same rendering as Combobox items: no visible control, a trailing check when selected.\n// Focus is on the item itself (roving via [data-pick-multi-item]).\nconst pickMultiItemClass = cn(menuItemButtonClass, 'min-w-0');\n\nfunction PickMultiItem({\n role,\n checked,\n label,\n onClick,\n}: {\n role: 'checkbox' | 'radio';\n checked: boolean;\n label: string;\n onClick: () => void;\n}) {\n return (\n <button\n type=\"button\"\n role={role}\n aria-checked={checked}\n data-selected={checked || undefined}\n data-pick-multi-item=\"\"\n title={label}\n className={pickMultiItemClass}\n onClick={onClick}\n >\n <span className=\"min-w-0 flex-1 truncate\">{label}</span>\n {checked && (\n <span className={menuItemCheckClass}>\n <CheckIcon />\n </span>\n )}\n </button>\n );\n}\n\ntype PickMultiField = Extract<PropertyFilterField, { kind: 'pick-multi' }>;\n\nexport type PickMultiPanelProps = {\n field: PickMultiField;\n tokens: PropertyFilterToken[];\n /** Always carries a value: an empty list is how the panel says \"nothing selected\". */\n onChange: (fieldId: string, value: string | string[]) => void;\n};\n\n/**\n * Reusable body for a pick-multi side popover: optional search input plus a\n * radio group (single-select) or checkbox list (when `field.multi` is true).\n * Shared between the Filter Creator's property-picker side popover and the\n * PropertyFilterApplied pill's inline editor so both surfaces use the exact same UI.\n */\nexport function PickMultiPanel({ field, tokens, onChange }: PickMultiPanelProps) {\n const [query, setQuery] = useState('');\n const listClassName = 'max-h-[80dvh] overflow-auto p-1';\n\n const filteredOptions = useMemo(() => {\n const q = query.trim().toLowerCase();\n if (!q) return field.options;\n return field.options.filter(o => o.label.toLowerCase().includes(q));\n }, [field.options, query]);\n\n const token = useMemo(() => tokens.find(t => t.fieldId === field.id), [tokens, field.id]);\n // Fall back to `defaultValue` when no token exists — lets view-toggle fields (e.g. List mode)\n // show their default option pre-selected before the user explicitly picks one.\n const selectedValue = typeof token?.value === 'string' ? token.value : !field.multi ? field.defaultValue : undefined;\n const selectedValues = useMemo<string[]>(() => {\n const value = token?.value;\n if (Array.isArray(value)) return value;\n if (typeof value === 'string') return [value];\n return [];\n }, [token]);\n\n return (\n <>\n {field.searchable !== false && (\n <div className={menuSearchClasses.container}>\n <SearchIcon className={menuSearchClasses.icon} />\n <input\n type=\"text\"\n value={query}\n onChange={e => setQuery(e.target.value)}\n placeholder={`Search ${field.label.toLowerCase()}...`}\n className={menuSearchClasses.input}\n {...passwordManagerOptOutProps}\n onKeyDown={e => {\n if (e.key !== 'ArrowDown') return;\n const panel = e.currentTarget.closest<HTMLElement>('[data-pick-multi-panel]');\n const first = panel?.querySelector<HTMLElement>('[data-pick-multi-item]:not([disabled])');\n if (!first) return;\n e.preventDefault();\n e.stopPropagation();\n first.focus();\n }}\n />\n </div>\n )}\n\n {field.isLoading ? (\n <div className={cn(menuEmptyClass, 'm-1')}>\n <Spinner size=\"sm\" className=\"size-3 text-muted-foreground\" />\n Loading options…\n </div>\n ) : filteredOptions.length === 0 ? (\n <div className={cn(menuEmptyClass, 'm-1')}>{field.emptyText ?? 'No option found.'}</div>\n ) : field.multi ? (\n <div className={listClassName}>\n <>\n {filteredOptions.map(option => {\n const checked = selectedValues.includes(option.value);\n return (\n <PickMultiItem\n key={option.value}\n role=\"checkbox\"\n checked={checked}\n label={option.label}\n onClick={() =>\n onChange(\n field.id,\n checked ? selectedValues.filter(v => v !== option.value) : [...selectedValues, option.value],\n )\n }\n />\n );\n })}\n </>\n </div>\n ) : (\n <div role=\"radiogroup\" className={listClassName}>\n <>\n {filteredOptions.map(option => (\n <PickMultiItem\n key={option.value}\n role=\"radio\"\n checked={selectedValue === option.value}\n label={option.label}\n onClick={() => onChange(field.id, option.value)}\n />\n ))}\n {!field.omitAnyOption && (\n <PickMultiItem\n role=\"radio\"\n checked={selectedValue === 'Any'}\n label=\"Any\"\n onClick={() => onChange(field.id, 'Any')}\n />\n )}\n </>\n </div>\n )}\n </>\n );\n}\n","import { LockIcon, XIcon } from 'lucide-react';\nimport type { ReactNode } from 'react';\nimport { useEffect, useRef, useState } from 'react';\nimport { Button } from '../Button';\nimport { ButtonsGroup, ButtonsGroupText } from '../ButtonsGroup';\nimport { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '../Tooltip';\nimport { PickMultiPanel } from './pick-multi-panel';\nimport type { PropertyFilterField, PropertyFilterToken } from './types';\nimport { Input } from '@/ds/components/Input';\nimport { Popover, PopoverContent, PopoverTrigger } from '@/ds/components/Popover/popover';\nimport { MENU_SIDE_OFFSET } from '@/ds/primitives/menu-item';\n\nexport type PropertyFilterAppliedProps = {\n fields: PropertyFilterField[];\n tokens: PropertyFilterToken[];\n onTokensChange: (tokens: PropertyFilterToken[]) => void;\n disabled?: boolean;\n /**\n * Field id that was just added via the Creator — rendered pill auto-focuses\n * its input so the user can start typing immediately.\n */\n autoFocusFieldId?: string;\n /**\n * Field ids whose pills must remain visible and read-only — value stays\n * displayed but cannot be edited or removed. Use when an upstream context\n * (e.g. agent-scoped traces tab) pre-applies a filter that the user must\n * not be able to clear.\n */\n lockedFieldIds?: readonly string[];\n /** Tooltip content shown on hover/focus of any locked pill. */\n lockedTooltipContent?: ReactNode;\n};\n\nfunction stringifyTokenValue(value: string | string[]) {\n if (Array.isArray(value)) return value.length === 0 ? 'Any' : value.join(', ');\n return value;\n}\n\nconst DEFAULT_LOCKED_TOOLTIP = 'This filter is set by the current context and cannot be removed here.';\n\nfunction lookupOptionLabel(field: PropertyFilterField, value: string | string[]): string {\n if (field.kind === 'pick-multi' && field.options) {\n if (Array.isArray(value)) {\n if (value.length === 0) return 'Any';\n return value.map(v => field.options.find(o => o.value === v)?.label ?? v).join(', ');\n }\n return field.options.find(o => o.value === value)?.label ?? value;\n }\n return stringifyTokenValue(value);\n}\n\ntype LockedTokenPillProps = {\n field: PropertyFilterField;\n value: string | string[];\n tooltipContent: ReactNode;\n};\n\nfunction LockedTokenPill({ field, value, tooltipContent }: LockedTokenPillProps) {\n const display = lookupOptionLabel(field, value);\n const lockA11yLabel = `${field.label} filter is locked by context`;\n\n return (\n <TooltipProvider delayDuration={150}>\n <Tooltip>\n <TooltipTrigger asChild>\n <ButtonsGroup\n data-locked-field-id={field.id}\n data-property-filter-pill=\"locked\"\n tabIndex={0}\n aria-label={lockA11yLabel}\n >\n <ButtonsGroupText>{field.label}</ButtonsGroupText>\n <ButtonsGroupText>is</ButtonsGroupText>\n <ButtonsGroupText>{display}</ButtonsGroupText>\n <ButtonsGroupText>\n <LockIcon />\n </ButtonsGroupText>\n </ButtonsGroup>\n </TooltipTrigger>\n <TooltipContent>{tooltipContent}</TooltipContent>\n </Tooltip>\n </TooltipProvider>\n );\n}\n\ntype TextTokenPillProps = {\n field: Extract<PropertyFilterField, { kind: 'text' }>;\n value: string;\n onChange: (value: string) => void;\n onRemove: () => void;\n disabled?: boolean;\n autoFocus?: boolean;\n};\n\nfunction TextTokenPill({ field, value, onChange, onRemove, disabled, autoFocus }: TextTokenPillProps) {\n // Local draft keeps the caret stable when the URL round-trip trims the\n // stored value (e.g. trailing spaces). We only re-sync from the prop when\n // the external value is genuinely different from our current (trimmed) draft.\n const [draft, setDraft] = useState(value);\n const inputRef = useRef<HTMLInputElement>(null);\n\n useEffect(() => {\n if (draft.trim() !== value) setDraft(value);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [value]);\n\n useEffect(() => {\n if (autoFocus) inputRef.current?.focus();\n }, [autoFocus]);\n\n return (\n <ButtonsGroup>\n <ButtonsGroupText>{field.label}</ButtonsGroupText>\n <ButtonsGroupText>is</ButtonsGroupText>\n <Input\n ref={inputRef}\n disabled={disabled}\n value={draft}\n placeholder={field.placeholder ?? `Enter ${field.label}`}\n onChange={e => {\n const next = e.target.value;\n setDraft(next);\n // Apply live — URL and traces query update on every keystroke.\n // Empty values persist as empty-value tokens so the pill stays visible.\n if (next.trim() !== value) onChange(next);\n }}\n onKeyDown={e => {\n if (e.key === 'Enter') {\n e.preventDefault();\n const trimmed = draft.trim();\n if (trimmed !== value) onChange(trimmed);\n } else if (e.key === 'Escape') {\n e.preventDefault();\n setDraft(value);\n e.currentTarget.blur();\n }\n }}\n />\n <Button\n size=\"icon-md\"\n type=\"button\"\n disabled={disabled}\n aria-label={`Remove ${field.label} filter`}\n onMouseDown={e => e.preventDefault()}\n onClick={onRemove}\n >\n <XIcon />\n </Button>\n </ButtonsGroup>\n );\n}\n\ntype PickMultiTokenPillProps = {\n field: Extract<PropertyFilterField, { kind: 'pick-multi' }>;\n token: PropertyFilterToken;\n tokens: PropertyFilterToken[];\n onChange: (fieldId: string, value: string | string[]) => void;\n onRemove: () => void;\n disabled?: boolean;\n};\n\nfunction PickMultiTokenPill({ field, token, tokens, onChange, onRemove, disabled }: PickMultiTokenPillProps) {\n const [open, setOpen] = useState(false);\n\n return (\n <ButtonsGroup>\n <ButtonsGroupText>{field.label}</ButtonsGroupText>\n <ButtonsGroupText>is</ButtonsGroupText>\n <Popover open={open} onOpenChange={setOpen}>\n <PopoverTrigger asChild>\n <Button type=\"button\" disabled={disabled}>\n {stringifyTokenValue(token.value)}\n </Button>\n </PopoverTrigger>\n <PopoverContent align=\"start\" sideOffset={MENU_SIDE_OFFSET} className=\"w-64 p-0\" data-pick-multi-panel>\n <PickMultiPanel field={field} tokens={tokens} onChange={onChange} />\n </PopoverContent>\n </Popover>\n <Button\n size=\"icon-md\"\n type=\"button\"\n disabled={disabled}\n aria-label={`Remove ${field.label} filter`}\n onClick={onRemove}\n >\n <XIcon />\n </Button>\n </ButtonsGroup>\n );\n}\n\n/**\n * Applied filter pills. Text/id-style tokens render with an always-active\n * input so the user can edit the value inline (and an empty token is valid —\n * it persists in the URL until the user explicitly removes it via ×).\n * Pick-multi tokens render with a clickable value that opens the same side\n * popover as the Filter Creator so the user can update selections in place.\n * Creation lives in a separate component (PropertyFilterCreator).\n */\nexport function PropertyFilterApplied({\n fields,\n tokens,\n onTokensChange,\n disabled,\n autoFocusFieldId,\n lockedFieldIds,\n lockedTooltipContent = DEFAULT_LOCKED_TOOLTIP,\n}: PropertyFilterAppliedProps) {\n if (tokens.length === 0) return null;\n\n const lockedSet = new Set(lockedFieldIds ?? []);\n\n const replaceTokenAt = (index: number, next: PropertyFilterToken) => {\n const copy = [...tokens];\n copy[index] = next;\n onTokensChange(copy);\n };\n\n const removeTokenAt = (index: number) => {\n onTokensChange(tokens.filter((_, i) => i !== index));\n };\n\n return (\n <div className=\"flex flex-wrap items-center gap-2\">\n {tokens.map((token, index) => {\n const field = fields.find(f => f.id === token.fieldId);\n if (!field) return null;\n\n if (lockedSet.has(token.fieldId)) {\n return (\n <LockedTokenPill\n key={`${token.fieldId}-${index}`}\n field={field}\n value={token.value}\n tooltipContent={lockedTooltipContent}\n />\n );\n }\n\n if (field.kind === 'text' && !Array.isArray(token.value)) {\n return (\n <TextTokenPill\n key={`${token.fieldId}-${index}`}\n field={field}\n value={token.value}\n disabled={disabled}\n autoFocus={autoFocusFieldId === token.fieldId}\n onChange={nextValue => replaceTokenAt(index, { fieldId: token.fieldId, value: nextValue })}\n onRemove={() => removeTokenAt(index)}\n />\n );\n }\n\n if (field.kind === 'pick-multi') {\n return (\n <PickMultiTokenPill\n key={`${token.fieldId}-${index}`}\n field={field}\n token={token}\n tokens={tokens}\n disabled={disabled}\n // Unselecting everything (empty array) keeps the pill alive in a\n // neutral state — the user explicitly removes it via ×. This lets\n // the page-level Reset neutralize values without dropping the pill.\n onChange={(fieldId, value) => replaceTokenAt(index, { fieldId, value })}\n onRemove={() => removeTokenAt(index)}\n />\n );\n }\n\n return (\n <ButtonsGroup key={`${token.fieldId}-${index}`}>\n <ButtonsGroupText>{field.label}</ButtonsGroupText>\n <ButtonsGroupText>is</ButtonsGroupText>\n <ButtonsGroupText>{stringifyTokenValue(token.value)}</ButtonsGroupText>\n <Button\n size=\"icon-md\"\n type=\"button\"\n disabled={disabled}\n aria-label={`Remove ${field.label} filter`}\n onClick={() => removeTokenAt(index)}\n >\n <XIcon />\n </Button>\n </ButtonsGroup>\n );\n })}\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAoBA,SAAgB,sBAAsB,EACpC,UACA,SACA,aACA,QACA,iBAC6B;CAC7B,MAAM,eAAe,CAAC,EAAE,eAAe,UAAU;CACjD,IAAI,CAAC,WAAW,CAAC,cAAc,OAAO;CAEtC,OACE,qBAAC,OAAD;EAAK,WAAU;EAAf,UAAA,CACG,WACC,oBAAC,QAAD;GAAkB;GAAU,MAAK;GAAK,SAAS;GAAS,MAAM,oBAAC,OAAD,CAAQ,CAAA;GAAG,UAAA;EAEjE,CAAA,GAGT,gBACC,qBAAC,cAAD,EAAA,UAAA,CACE,oBAAC,aAAa,SAAd;GAAsB,SAAA;GACpB,UAAA,oBAAC,QAAD;IAAkB;IAAU,MAAK;IAAU,cAAW;IACpD,UAAA,oBAAC,sBAAD,CAAuB,CAAA;GACjB,CAAA;EACY,CAAA,GACtB,qBAAC,aAAa,SAAd;GAAsB,OAAM;GAA5B,UAAA;IACG,eACC,qBAAC,aAAa,MAAd;KAAmB,gBAAgB,YAAY;KAA/C,UAAA,CACE,oBAAC,OAAD,CAAQ,CAAA,GAAC,oBAEQ;;IAEpB,gBAAgB,UAAU,kBAAkB,oBAAC,aAAa,WAAd,CAAyB,CAAA;IACrE,UACC,qBAAC,aAAa,MAAd;KAAmB,gBAAgB,OAAO;KAA1C,UAAA,CACE,oBAAC,UAAD,CAAW,CAAA,GAAC,4BAEK;;IAEpB,iBACC,qBAAC,aAAa,MAAd;KAAmB,gBAAgB,cAAc;KAAjD,UAAA,CACE,oBAAC,YAAD,CAAa,CAAA,GAAC,sBAEG;;GAED;EACV,CAAA,CAAA,EAAA,CAAA,CAEb;;AAET;;AC5DA,IAAM,qBAAqB,GAAG,qBAAqB,SAAS;AAE5D,SAAS,cAAc,EACrB,MACA,SACA,OACA,WAMC;CACD,OACE,qBAAC,UAAD;EACE,MAAK;EACC;EACN,gBAAc;EACd,iBAAe,WAAW,KAAA;EAC1B,wBAAqB;EACrB,OAAO;EACP,WAAW;EACF;EARX,UAAA,CAUE,oBAAC,QAAD;GAAM,WAAU;GAA2B,UAAA;EAAY,CAAA,GACtD,WACC,oBAAC,QAAD;GAAM,WAAW;GACf,UAAA,oBAAC,WAAD,CAAY,CAAA;EACR,CAAA,CAEF;;AAEZ;;;;;;;AAiBA,SAAgB,eAAe,EAAE,OAAO,QAAQ,YAAiC;CAC/E,MAAM,CAAC,OAAO,YAAY,SAAS,EAAE;CACrC,MAAM,gBAAgB;CAEtB,MAAM,kBAAkB,cAAc;EACpC,MAAM,IAAI,MAAM,KAAK,CAAC,CAAC,YAAY;EACnC,IAAI,CAAC,GAAG,OAAO,MAAM;EACrB,OAAO,MAAM,QAAQ,QAAO,MAAK,EAAE,MAAM,YAAY,CAAC,CAAC,SAAS,CAAC,CAAC;CACpE,GAAG,CAAC,MAAM,SAAS,KAAK,CAAC;CAEzB,MAAM,QAAQ,cAAc,OAAO,MAAK,MAAK,EAAE,YAAY,MAAM,EAAE,GAAG,CAAC,QAAQ,MAAM,EAAE,CAAC;CAGxF,MAAM,gBAAgB,OAAO,OAAO,UAAU,WAAW,MAAM,QAAQ,CAAC,MAAM,QAAQ,MAAM,eAAe,KAAA;CAC3G,MAAM,iBAAiB,cAAwB;EAC7C,MAAM,QAAQ,OAAO;EACrB,IAAI,MAAM,QAAQ,KAAK,GAAG,OAAO;EACjC,IAAI,OAAO,UAAU,UAAU,OAAO,CAAC,KAAK;EAC5C,OAAO,CAAC;CACV,GAAG,CAAC,KAAK,CAAC;CAEV,OACE,qBAAAA,YAAA,EAAA,UAAA,CACG,MAAM,eAAe,SACpB,qBAAC,OAAD;EAAK,WAAW,kBAAkB;EAAlC,UAAA,CACE,oBAAC,YAAD,EAAY,WAAW,kBAAkB,KAAO,CAAA,GAChD,oBAAC,SAAD;GACE,MAAK;GACL,OAAO;GACP,WAAU,MAAK,SAAS,EAAE,OAAO,KAAK;GACtC,aAAa,UAAU,MAAM,MAAM,YAAY,EAAE;GACjD,WAAW,kBAAkB;GAC7B,GAAI;GACJ,YAAW,MAAK;IACd,IAAI,EAAE,QAAQ,aAAa;IAE3B,MAAM,QADQ,EAAE,cAAc,QAAqB,yBACrC,CAAA,EAAO,cAA2B,wCAAwC;IACxF,IAAI,CAAC,OAAO;IACZ,EAAE,eAAe;IACjB,EAAE,gBAAgB;IAClB,MAAM,MAAM;GACd;EACD,CAAA,CACE;CAGN,CAAA,GAAA,MAAM,YACL,qBAAC,OAAD;EAAK,WAAW,GAAG,gBAAgB,KAAK;EAAxC,UAAA,CACE,oBAAC,SAAD;GAAS,MAAK;GAAK,WAAU;EAAgC,CAAA,GAAC,kBAE3D;CACH,CAAA,IAAA,gBAAgB,WAAW,IAC7B,oBAAC,OAAD;EAAK,WAAW,GAAG,gBAAgB,KAAK;EAAI,UAAA,MAAM,aAAa;CAAwB,CAAA,IACrF,MAAM,QACR,oBAAC,OAAD;EAAK,WAAW;EACd,UAAA,oBAAAA,YAAA,EAAA,UACG,gBAAgB,KAAI,WAAU;GAC7B,MAAM,UAAU,eAAe,SAAS,OAAO,KAAK;GACpD,OACE,oBAAC,eAAD;IAEE,MAAK;IACI;IACT,OAAO,OAAO;IACd,eACE,SACE,MAAM,IACN,UAAU,eAAe,QAAO,MAAK,MAAM,OAAO,KAAK,IAAI,CAAC,GAAG,gBAAgB,OAAO,KAAK,CAC7F;GAEH,GAVM,OAAO,KAUb;EAEL,CAAC,EACD,CAAA;CACC,CAAA,IAEL,oBAAC,OAAD;EAAK,MAAK;EAAa,WAAW;EAChC,UAAA,qBAAAA,YAAA,EAAA,UAAA,CACG,gBAAgB,KAAI,WACnB,oBAAC,eAAD;GAEE,MAAK;GACL,SAAS,kBAAkB,OAAO;GAClC,OAAO,OAAO;GACd,eAAe,SAAS,MAAM,IAAI,OAAO,KAAK;EAC/C,GALM,OAAO,KAKb,CACF,GACA,CAAC,MAAM,iBACN,oBAAC,eAAD;GACE,MAAK;GACL,SAAS,kBAAkB;GAC3B,OAAM;GACN,eAAe,SAAS,MAAM,IAAI,KAAK;EACxC,CAAA,CAEH,EAAA,CAAA;CACC,CAAA,CAEP,EAAA,CAAA;AAEN;;AC9HA,SAAS,oBAAoB,OAA0B;CACrD,IAAI,MAAM,QAAQ,KAAK,GAAG,OAAO,MAAM,WAAW,IAAI,QAAQ,MAAM,KAAK,IAAI;CAC7E,OAAO;AACT;AAEA,IAAM,yBAAyB;AAE/B,SAAS,kBAAkB,OAA4B,OAAkC;CACvF,IAAI,MAAM,SAAS,gBAAgB,MAAM,SAAS;EAChD,IAAI,MAAM,QAAQ,KAAK,GAAG;GACxB,IAAI,MAAM,WAAW,GAAG,OAAO;GAC/B,OAAO,MAAM,KAAI,MAAK,MAAM,QAAQ,MAAK,MAAK,EAAE,UAAU,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC,CAAC,KAAK,IAAI;EACrF;EACA,OAAO,MAAM,QAAQ,MAAK,MAAK,EAAE,UAAU,KAAK,CAAC,EAAE,SAAS;CAC9D;CACA,OAAO,oBAAoB,KAAK;AAClC;AAQA,SAAS,gBAAgB,EAAE,OAAO,OAAO,kBAAwC;CAC/E,MAAM,UAAU,kBAAkB,OAAO,KAAK;CAC9C,MAAM,gBAAgB,GAAG,MAAM,MAAM;CAErC,OACE,oBAAC,iBAAD;EAAiB,eAAe;EAC9B,UAAA,qBAAC,SAAD,EAAA,UAAA,CACE,oBAAC,gBAAD;GAAgB,SAAA;GACd,UAAA,qBAAC,cAAD;IACE,wBAAsB,MAAM;IAC5B,6BAA0B;IAC1B,UAAU;IACV,cAAY;IAJd,UAAA;KAME,oBAAC,kBAAD,EAAA,UAAmB,MAAM,MAAwB,CAAA;KACjD,oBAAC,kBAAD,EAAA,UAAkB,KAAoB,CAAA;KACtC,oBAAC,kBAAD,EAAA,UAAmB,QAA0B,CAAA;KAC7C,oBAAC,kBAAD,EAAA,UACE,oBAAC,UAAD,CAAW,CAAA,EACK,CAAA;IACN;;EACA,CAAA,GAChB,oBAAC,gBAAD,EAAA,UAAiB,eAA+B,CAAA,CACzC,EAAA,CAAA;CACM,CAAA;AAErB;AAWA,SAAS,cAAc,EAAE,OAAO,OAAO,UAAU,UAAU,UAAU,aAAiC;CAIpG,MAAM,CAAC,OAAO,YAAY,SAAS,KAAK;CACxC,MAAM,WAAW,OAAyB,IAAI;CAE9C,gBAAgB;EACd,IAAI,MAAM,KAAK,MAAM,OAAO,SAAS,KAAK;CAE5C,GAAG,CAAC,KAAK,CAAC;CAEV,gBAAgB;EACd,IAAI,WAAW,SAAS,SAAS,MAAM;CACzC,GAAG,CAAC,SAAS,CAAC;CAEd,OACE,qBAAC,cAAD,EAAA,UAAA;EACE,oBAAC,kBAAD,EAAA,UAAmB,MAAM,MAAwB,CAAA;EACjD,oBAAC,kBAAD,EAAA,UAAkB,KAAoB,CAAA;EACtC,oBAAC,OAAD;GACE,KAAK;GACK;GACV,OAAO;GACP,aAAa,MAAM,eAAe,SAAS,MAAM;GACjD,WAAU,MAAK;IACb,MAAM,OAAO,EAAE,OAAO;IACtB,SAAS,IAAI;IAGb,IAAI,KAAK,KAAK,MAAM,OAAO,SAAS,IAAI;GAC1C;GACA,YAAW,MAAK;IACd,IAAI,EAAE,QAAQ,SAAS;KACrB,EAAE,eAAe;KACjB,MAAM,UAAU,MAAM,KAAK;KAC3B,IAAI,YAAY,OAAO,SAAS,OAAO;IACzC,OAAO,IAAI,EAAE,QAAQ,UAAU;KAC7B,EAAE,eAAe;KACjB,SAAS,KAAK;KACd,EAAE,cAAc,KAAK;IACvB;GACF;EACD,CAAA;EACD,oBAAC,QAAD;GACE,MAAK;GACL,MAAK;GACK;GACV,cAAY,UAAU,MAAM,MAAM;GAClC,cAAa,MAAK,EAAE,eAAe;GACnC,SAAS;GAET,UAAA,oBAAC,OAAD,CAAQ,CAAA;EACF,CAAA;CACI,EAAA,CAAA;AAElB;AAWA,SAAS,mBAAmB,EAAE,OAAO,OAAO,QAAQ,UAAU,UAAU,YAAqC;CAC3G,MAAM,CAAC,MAAM,WAAW,SAAS,KAAK;CAEtC,OACE,qBAAC,cAAD,EAAA,UAAA;EACE,oBAAC,kBAAD,EAAA,UAAmB,MAAM,MAAwB,CAAA;EACjD,oBAAC,kBAAD,EAAA,UAAkB,KAAoB,CAAA;EACtC,qBAAC,SAAD;GAAe;GAAM,cAAc;GAAnC,UAAA,CACE,oBAAC,gBAAD;IAAgB,SAAA;IACd,UAAA,oBAAC,QAAD;KAAQ,MAAK;KAAmB;KAC7B,UAAA,oBAAoB,MAAM,KAAK;IAC1B,CAAA;GACM,CAAA,GAChB,oBAAC,gBAAD;IAAgB,OAAM;IAAQ,YAAA;IAA8B,WAAU;IAAW,yBAAA;IAC/E,UAAA,oBAAC,gBAAD;KAAuB;KAAe;KAAkB;IAAW,CAAA;GACrD,CAAA,CACT;;EACT,oBAAC,QAAD;GACE,MAAK;GACL,MAAK;GACK;GACV,cAAY,UAAU,MAAM,MAAM;GAClC,SAAS;GAET,UAAA,oBAAC,OAAD,CAAQ,CAAA;EACF,CAAA;CACI,EAAA,CAAA;AAElB;;;;;;;;;AAUA,SAAgB,sBAAsB,EACpC,QACA,QACA,gBACA,UACA,kBACA,gBACA,uBAAuB,0BACM;CAC7B,IAAI,OAAO,WAAW,GAAG,OAAO;CAEhC,MAAM,YAAY,IAAI,IAAI,kBAAkB,CAAC,CAAC;CAE9C,MAAM,kBAAkB,OAAe,SAA8B;EACnE,MAAM,OAAO,CAAC,GAAG,MAAM;EACvB,KAAK,SAAS;EACd,eAAe,IAAI;CACrB;CAEA,MAAM,iBAAiB,UAAkB;EACvC,eAAe,OAAO,QAAQ,GAAG,MAAM,MAAM,KAAK,CAAC;CACrD;CAEA,OACE,oBAAC,OAAD;EAAK,WAAU;EACZ,UAAA,OAAO,KAAK,OAAO,UAAU;GAC5B,MAAM,QAAQ,OAAO,MAAK,MAAK,EAAE,OAAO,MAAM,OAAO;GACrD,IAAI,CAAC,OAAO,OAAO;GAEnB,IAAI,UAAU,IAAI,MAAM,OAAO,GAC7B,OACE,oBAAC,iBAAD;IAES;IACP,OAAO,MAAM;IACb,gBAAgB;GACjB,GAJM,GAAG,MAAM,QAAQ,GAAG,OAI1B;GAIL,IAAI,MAAM,SAAS,UAAU,CAAC,MAAM,QAAQ,MAAM,KAAK,GACrD,OACE,oBAAC,eAAD;IAES;IACP,OAAO,MAAM;IACH;IACV,WAAW,qBAAqB,MAAM;IACtC,WAAU,cAAa,eAAe,OAAO;KAAE,SAAS,MAAM;KAAS,OAAO;IAAU,CAAC;IACzF,gBAAgB,cAAc,KAAK;GACpC,GAPM,GAAG,MAAM,QAAQ,GAAG,OAO1B;GAIL,IAAI,MAAM,SAAS,cACjB,OACE,oBAAC,oBAAD;IAES;IACA;IACC;IACE;IAIV,WAAW,SAAS,UAAU,eAAe,OAAO;KAAE;KAAS;IAAM,CAAC;IACtE,gBAAgB,cAAc,KAAK;GACpC,GAVM,GAAG,MAAM,QAAQ,GAAG,OAU1B;GAIL,OACE,qBAAC,cAAD,EAAA,UAAA;IACE,oBAAC,kBAAD,EAAA,UAAmB,MAAM,MAAwB,CAAA;IACjD,oBAAC,kBAAD,EAAA,UAAkB,KAAoB,CAAA;IACtC,oBAAC,kBAAD,EAAA,UAAmB,oBAAoB,MAAM,KAAK,EAAoB,CAAA;IACtE,oBAAC,QAAD;KACE,MAAK;KACL,MAAK;KACK;KACV,cAAY,UAAU,MAAM,MAAM;KAClC,eAAe,cAAc,KAAK;KAElC,UAAA,oBAAC,OAAD,CAAQ,CAAA;IACF,CAAA;GACI,EAAA,GAbK,GAAG,MAAM,QAAQ,GAAG,OAazB;EAElB,CAAC;CACE,CAAA;AAET"}