@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.
- package/dist/{DataCodeSection-CcPmJPTp.cjs → DataCodeSection-CFxXsQWH.cjs} +3 -3
- package/dist/DataCodeSection-CFxXsQWH.cjs.map +1 -0
- package/dist/{DataCodeSection-KJRyRD1Q.js → DataCodeSection-PY9XEg2C.js} +3 -3
- package/dist/DataCodeSection-PY9XEg2C.js.map +1 -0
- package/dist/{DataPanel-BwB1Oifd.cjs → DataPanel-Coc9h35I.cjs} +2 -2
- package/dist/{DataPanel-BwB1Oifd.cjs.map → DataPanel-Coc9h35I.cjs.map} +1 -1
- package/dist/{DataPanel-Bv4M17xO.js → DataPanel-IgB9D5PO.js} +2 -2
- package/dist/{DataPanel-Bv4M17xO.js.map → DataPanel-IgB9D5PO.js.map} +1 -1
- package/dist/{FilterBar-BO-vvvyq.js → FilterBar-BgW2dqRQ.js} +7 -7
- package/dist/FilterBar-BgW2dqRQ.js.map +1 -0
- package/dist/{FilterBar-Buw0tv51.cjs → FilterBar-CQl04O6t.cjs} +7 -7
- package/dist/FilterBar-CQl04O6t.cjs.map +1 -0
- package/dist/{MetricsTable-D-aZf3dk.cjs → MetricsTable-BSl81oNe.cjs} +44 -9
- package/dist/MetricsTable-BSl81oNe.cjs.map +1 -0
- package/dist/{MetricsTable-CRPeLHe1.js → MetricsTable-DID6LRoP.js} +44 -9
- package/dist/MetricsTable-DID6LRoP.js.map +1 -0
- package/dist/{ask-user-DdYz56qH.cjs → ask-user-C1p2PEYe.cjs} +2 -2
- package/dist/ask-user-C1p2PEYe.cjs.map +1 -0
- package/dist/{ask-user-B225wzWc.js → ask-user-DPznrqGO.js} +2 -2
- package/dist/ask-user-DPznrqGO.js.map +1 -0
- package/dist/chart-plot.css +5 -4
- package/dist/{combobox-CtCK0mNx.js → combobox-D21no8t5.js} +4 -4
- package/dist/{combobox-CtCK0mNx.js.map → combobox-D21no8t5.js.map} +1 -1
- package/dist/{combobox-CMx2ayFN.cjs → combobox-DIT_6xiG.cjs} +4 -4
- package/dist/combobox-DIT_6xiG.cjs.map +1 -0
- package/dist/{combobox-parts-ScKcYjMR.cjs → combobox-parts-C4phOq4t.cjs} +2 -2
- package/dist/combobox-parts-C4phOq4t.cjs.map +1 -0
- package/dist/{combobox-parts-C1CugUAU.js → combobox-parts-D90ir0Py.js} +3 -3
- package/dist/combobox-parts-D90ir0Py.js.map +1 -0
- package/dist/components/Combobox.cjs.js +2 -2
- package/dist/components/Combobox.es.js +2 -2
- package/dist/components/Command.cjs.js +1 -1
- package/dist/components/Command.cjs.js.map +1 -1
- package/dist/components/Command.es.js +1 -1
- package/dist/components/Command.es.js.map +1 -1
- package/dist/components/DataCodeSection.cjs.js +1 -1
- package/dist/components/DataCodeSection.es.js +1 -1
- package/dist/components/DataList.cjs.js +1 -1
- package/dist/components/DataList.es.js +1 -1
- package/dist/components/DataPanel.cjs.js +1 -1
- package/dist/components/DataPanel.es.js +1 -1
- package/dist/components/DateTimePicker.cjs.js +1 -1
- package/dist/components/DateTimePicker.cjs.js.map +1 -1
- package/dist/components/DateTimePicker.es.js +1 -1
- package/dist/components/DateTimePicker.es.js.map +1 -1
- package/dist/components/FilterBar.cjs.js +3 -3
- package/dist/components/FilterBar.es.js +3 -3
- package/dist/components/FormFieldBlocks.cjs.js +1 -1
- package/dist/components/FormFieldBlocks.cjs.js.map +1 -1
- package/dist/components/FormFieldBlocks.es.js +1 -1
- package/dist/components/FormFieldBlocks.es.js.map +1 -1
- package/dist/components/MetricsTable.cjs.js +1 -1
- package/dist/components/MetricsTable.es.js +1 -1
- package/dist/components/PropertyFilter.cjs.js +3 -3
- package/dist/components/PropertyFilter.cjs.js.map +1 -1
- package/dist/components/PropertyFilter.es.js +3 -3
- package/dist/components/PropertyFilter.es.js.map +1 -1
- package/dist/components/SavedViews.cjs.js +1 -1
- package/dist/components/SavedViews.es.js +1 -1
- package/dist/components/Sidebar.cjs.js +8 -8
- package/dist/components/Sidebar.cjs.js.map +1 -1
- package/dist/components/Sidebar.es.js +9 -9
- package/dist/components/Sidebar.es.js.map +1 -1
- package/dist/components/ai/ask-user.cjs.js +1 -1
- package/dist/components/ai/ask-user.es.js +1 -1
- package/dist/domains/chat/tools/badges/ask-user-badge.cjs.js +1 -1
- package/dist/domains/chat/tools/badges/ask-user-badge.es.js +1 -1
- package/dist/domains/dashboards/kinds/table/table-view.cjs.js +1 -1
- package/dist/domains/dashboards/kinds/table/table-view.es.js +1 -1
- package/dist/domains/dashboards/metrics-dashboard.cjs.js +1 -1
- package/dist/domains/dashboards/metrics-dashboard.cjs.js.map +1 -1
- package/dist/domains/dashboards/metrics-dashboard.es.js +1 -1
- package/dist/domains/dashboards/metrics-dashboard.es.js.map +1 -1
- package/dist/domains/datasets/components/save-as-dataset-item-dialog.cjs.js +1 -1
- package/dist/domains/datasets/components/save-as-dataset-item-dialog.es.js +1 -1
- package/dist/domains/logs/components/log-data-panel.cjs.js +1 -1
- package/dist/domains/logs/components/log-data-panel.es.js +1 -1
- package/dist/domains/logs/components/logs-saved-views.cjs.js +1 -1
- package/dist/domains/logs/components/logs-saved-views.es.js +1 -1
- package/dist/domains/logs/components/logs-toolbar.cjs.js +1 -1
- package/dist/domains/logs/components/logs-toolbar.es.js +1 -1
- package/dist/domains/metrics/components/breakdown/breakdown-table.cjs.js +2 -2
- package/dist/domains/metrics/components/breakdown/breakdown-table.cjs.js.map +1 -1
- package/dist/domains/metrics/components/breakdown/breakdown-table.es.js +2 -2
- package/dist/domains/metrics/components/breakdown/breakdown-table.es.js.map +1 -1
- package/dist/domains/metrics/components/metrics-time-range-chip.cjs.js +1 -1
- package/dist/domains/metrics/components/metrics-time-range-chip.es.js +1 -1
- package/dist/domains/observability/saved-views/observability-saved-views.cjs.js +1 -1
- package/dist/domains/observability/saved-views/observability-saved-views.es.js +1 -1
- package/dist/domains/observability/saved-views.cjs.js +1 -1
- package/dist/domains/observability/saved-views.es.js +1 -1
- package/dist/domains/observability.cjs.js +1 -1
- package/dist/domains/observability.es.js +1 -1
- package/dist/domains/scores/components/score-data-panel.cjs.js +1 -1
- package/dist/domains/scores/components/score-data-panel.es.js +1 -1
- package/dist/domains/scores/components/span-scoring.cjs.js +3 -3
- package/dist/domains/scores/components/span-scoring.cjs.js.map +1 -1
- package/dist/domains/scores/components/span-scoring.es.js +3 -3
- package/dist/domains/scores/components/span-scoring.es.js.map +1 -1
- package/dist/domains/skills/skill-simple-form.cjs.js +1 -1
- package/dist/domains/skills/skill-simple-form.cjs.js.map +1 -1
- package/dist/domains/skills/skill-simple-form.es.js +1 -1
- package/dist/domains/skills/skill-simple-form.es.js.map +1 -1
- package/dist/domains/spans/components/spans-explorer-body.cjs.js +1 -1
- package/dist/domains/spans/components/spans-explorer-body.es.js +1 -1
- package/dist/domains/spans/components/spans-filter-bar.cjs.js +3 -3
- package/dist/domains/spans/components/spans-filter-bar.cjs.js.map +1 -1
- package/dist/domains/spans/components/spans-filter-bar.es.js +3 -3
- package/dist/domains/spans/components/spans-filter-bar.es.js.map +1 -1
- package/dist/domains/spans/hooks/use-spans-filter-bar.cjs.js +1 -1
- package/dist/domains/spans/hooks/use-spans-filter-bar.es.js +1 -1
- package/dist/domains/threads/components/threads-explorer-body.cjs.js +1 -1
- package/dist/domains/threads/components/threads-explorer-body.es.js +1 -1
- package/dist/domains/threads/components/threads-filter-bar.cjs.js +3 -3
- package/dist/domains/threads/components/threads-filter-bar.cjs.js.map +1 -1
- package/dist/domains/threads/components/threads-filter-bar.es.js +3 -3
- package/dist/domains/threads/components/threads-filter-bar.es.js.map +1 -1
- package/dist/domains/threads/hooks/use-threads-filter-bar.cjs.js +1 -1
- package/dist/domains/threads/hooks/use-threads-filter-bar.es.js +1 -1
- package/dist/domains/traces/components/feedback-thread.cjs.js +1 -1
- package/dist/domains/traces/components/feedback-thread.cjs.js.map +1 -1
- package/dist/domains/traces/components/feedback-thread.es.js +1 -1
- package/dist/domains/traces/components/feedback-thread.es.js.map +1 -1
- package/dist/domains/traces/components/span-data-panel-view.cjs.js +1 -1
- package/dist/domains/traces/components/span-data-panel-view.es.js +1 -1
- package/dist/domains/traces/components/span-summary-description.cjs.js +1 -1
- package/dist/domains/traces/components/span-summary-description.es.js +1 -1
- package/dist/domains/traces/components/thread-trace/thread-trace-details.cjs.js +1 -1
- package/dist/domains/traces/components/thread-trace/thread-trace-details.es.js +1 -1
- package/dist/domains/traces/components/trace-columns-menu.cjs.js +3 -3
- package/dist/domains/traces/components/trace-columns-menu.cjs.js.map +1 -1
- package/dist/domains/traces/components/trace-columns-menu.es.js +3 -3
- package/dist/domains/traces/components/trace-columns-menu.es.js.map +1 -1
- package/dist/domains/traces/components/trace-data-panel-view.cjs.js +2 -2
- package/dist/domains/traces/components/trace-data-panel-view.cjs.js.map +1 -1
- package/dist/domains/traces/components/trace-data-panel-view.es.js +2 -2
- package/dist/domains/traces/components/trace-data-panel-view.es.js.map +1 -1
- package/dist/domains/traces/components/trace-id-button.cjs.js +1 -1
- package/dist/domains/traces/components/trace-id-button.es.js +1 -1
- package/dist/domains/traces/components/trace-summary-description.cjs.js +1 -1
- package/dist/domains/traces/components/trace-summary-description.es.js +1 -1
- package/dist/domains/traces/components/trace-thread-panel.cjs.js +1 -1
- package/dist/domains/traces/components/trace-thread-panel.es.js +1 -1
- package/dist/domains/traces/components/traces-explorer/traces-explorer-filter-bar.cjs.js +3 -3
- package/dist/domains/traces/components/traces-explorer/traces-explorer-filter-bar.cjs.js.map +1 -1
- package/dist/domains/traces/components/traces-explorer/traces-explorer-filter-bar.es.js +3 -3
- package/dist/domains/traces/components/traces-explorer/traces-explorer-filter-bar.es.js.map +1 -1
- package/dist/domains/traces/components/traces-explorer/traces-explorer-saved-views.cjs.js +1 -1
- package/dist/domains/traces/components/traces-explorer/traces-explorer-saved-views.es.js +1 -1
- package/dist/domains/traces/components/traces-explorer/use-traces-filter-bar.cjs.js +1 -1
- package/dist/domains/traces/components/traces-explorer/use-traces-filter-bar.es.js +1 -1
- package/dist/domains/workflows/components/workflow-combobox.cjs.js +2 -2
- package/dist/domains/workflows/components/workflow-combobox.cjs.js.map +1 -1
- package/dist/domains/workflows/components/workflow-combobox.es.js +2 -2
- package/dist/domains/workflows/components/workflow-combobox.es.js.map +1 -1
- package/dist/domains/workflows/workflow/input/workflow-processor-input.cjs.js +1 -1
- package/dist/domains/workflows/workflow/input/workflow-processor-input.cjs.js.map +1 -1
- package/dist/domains/workflows/workflow/input/workflow-processor-input.es.js +1 -1
- package/dist/domains/workflows/workflow/input/workflow-processor-input.es.js.map +1 -1
- package/dist/domains/workspace/components/workspace-add-skill-dialog.cjs.js +1 -1
- package/dist/domains/workspace/components/workspace-add-skill-dialog.cjs.js.map +1 -1
- package/dist/domains/workspace/components/workspace-add-skill-dialog.es.js +1 -1
- package/dist/domains/workspace/components/workspace-add-skill-dialog.es.js.map +1 -1
- package/dist/{filter-bar-chip-B4sV4gDm.js → filter-bar-chip-CABeKrtf.js} +4 -4
- package/dist/{filter-bar-chip-B4sV4gDm.js.map → filter-bar-chip-CABeKrtf.js.map} +1 -1
- package/dist/{filter-bar-chip-CIEsWcEw.cjs → filter-bar-chip-Cg-UbIwP.cjs} +4 -4
- package/dist/{filter-bar-chip-CIEsWcEw.cjs.map → filter-bar-chip-Cg-UbIwP.cjs.map} +1 -1
- package/dist/{filter-bar-time-range-DvuaFnkI.cjs → filter-bar-time-range-BA-pXMlo.cjs} +2 -2
- package/dist/{filter-bar-time-range-DvuaFnkI.cjs.map → filter-bar-time-range-BA-pXMlo.cjs.map} +1 -1
- package/dist/{filter-bar-time-range-CXQMBgpz.js → filter-bar-time-range-mg9JeYue.js} +2 -2
- package/dist/{filter-bar-time-range-CXQMBgpz.js.map → filter-bar-time-range-mg9JeYue.js.map} +1 -1
- package/dist/layout/tabbed-container.cjs.js +1 -1
- package/dist/layout/tabbed-container.es.js +1 -1
- package/dist/{observability-saved-views-BBam8Fr5.js → observability-saved-views-CjKTEp1V.js} +3 -3
- package/dist/observability-saved-views-CjKTEp1V.js.map +1 -0
- package/dist/{observability-saved-views-BAzxxoAr.cjs → observability-saved-views-Daizz4tU.cjs} +3 -3
- package/dist/observability-saved-views-Daizz4tU.cjs.map +1 -0
- package/dist/primitives/chart-plot.cjs.js +8 -6
- package/dist/primitives/chart-plot.cjs.js.map +1 -1
- package/dist/primitives/chart-plot.es.js +8 -6
- package/dist/primitives/chart-plot.es.js.map +1 -1
- package/dist/primitives/control-icon.cjs.js.map +1 -1
- package/dist/primitives/control-icon.es.js.map +1 -1
- package/dist/{property-filter-applied-p3dTTDdb.js → property-filter-applied--U5EZdaA.js} +2 -2
- package/dist/property-filter-applied--U5EZdaA.js.map +1 -0
- package/dist/{property-filter-applied-BCeRLcXb.cjs → property-filter-applied-BkkIObRq.cjs} +2 -2
- package/dist/property-filter-applied-BkkIObRq.cjs.map +1 -0
- package/dist/src/ds/components/MetricsTable/metrics-table-rows.d.ts +10 -3
- package/dist/src/ds/components/MetricsTable/metrics-table.d.ts +1 -1
- package/dist/style.css +14 -1
- package/dist/{tabbed-container-DQU7pVio.cjs → tabbed-container-B4lCBgRP.cjs} +2 -2
- package/dist/{tabbed-container-DQU7pVio.cjs.map → tabbed-container-B4lCBgRP.cjs.map} +1 -1
- package/dist/{tabbed-container-5j6dhoRX.js → tabbed-container-DI1GI1Qv.js} +2 -2
- package/dist/{tabbed-container-5j6dhoRX.js.map → tabbed-container-DI1GI1Qv.js.map} +1 -1
- package/oxlint/index.js +90 -0
- package/package.json +8 -8
- package/theme.css +4 -3
- package/dist/DataCodeSection-CcPmJPTp.cjs.map +0 -1
- package/dist/DataCodeSection-KJRyRD1Q.js.map +0 -1
- package/dist/FilterBar-BO-vvvyq.js.map +0 -1
- package/dist/FilterBar-Buw0tv51.cjs.map +0 -1
- package/dist/MetricsTable-CRPeLHe1.js.map +0 -1
- package/dist/MetricsTable-D-aZf3dk.cjs.map +0 -1
- package/dist/ask-user-B225wzWc.js.map +0 -1
- package/dist/ask-user-DdYz56qH.cjs.map +0 -1
- package/dist/combobox-CMx2ayFN.cjs.map +0 -1
- package/dist/combobox-parts-C1CugUAU.js.map +0 -1
- package/dist/combobox-parts-ScKcYjMR.cjs.map +0 -1
- package/dist/observability-saved-views-BAzxxoAr.cjs.map +0 -1
- package/dist/observability-saved-views-BBam8Fr5.js.map +0 -1
- package/dist/property-filter-applied-BCeRLcXb.cjs.map +0 -1
- package/dist/property-filter-applied-p3dTTDdb.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PropertyFilter.cjs.js","names":["forwardRef","useMemo","useState","useRef","useCallback","Popover","PopoverTrigger","Button","ListFilterPlusIcon","PopoverContent","cn","ArrowLeftIcon","FilterIcon","Txt","_Fragment","menuItemButtonClass","menuItemTrailingIconClass","PlusIcon","Field","Combobox","FieldError","X","ListFilterPlus","ChevronRightIcon","PickMultiPanel"],"sources":["../../src/ds/components/PropertyFilter/property-filter-creator.tsx"],"sourcesContent":["import {\n ArrowLeftIcon,\n ChevronRightIcon,\n FilterIcon,\n ListFilterPlusIcon,\n PlusIcon,\n ListFilterPlus,\n X,\n} from 'lucide-react';\nimport { forwardRef, useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport type { ButtonHTMLAttributes } from 'react';\nimport { PickMultiPanel } from './pick-multi-panel';\nimport type { PropertyFilterField, PropertyFilterToken } from './types';\nimport { Button } from '@/ds/components/Button/Button';\nimport type { ButtonProps } from '@/ds/components/Button/Button';\nimport { Combobox } from '@/ds/components/Combobox/combobox';\nimport { Field, FieldError } from '@/ds/components/Field';\nimport { Popover, PopoverContent, PopoverTrigger } from '@/ds/components/Popover/popover';\nimport { Txt } from '@/ds/components/Txt';\nimport {\n MENU_SIDE_OFFSET,\n menuEmptyClass,\n menuItemButtonClass,\n menuItemTrailingIconClass,\n} from '@/ds/primitives/menu-item';\nimport { controlStateColorTransition } from '@/ds/primitives/transitions';\nimport { quietTextHover } from '@/ds/primitives/typography';\nimport { cn } from '@/lib/utils';\n\n// Plain <button>s navigated with roving focus (not Base UI).\nconst FilterMenuButton = forwardRef<HTMLButtonElement, ButtonHTMLAttributes<HTMLButtonElement>>((props, ref) => (\n <button type=\"button\" role=\"menuitem\" data-filter-item=\"\" ref={ref} {...props} />\n));\nFilterMenuButton.displayName = 'FilterMenuButton';\n\nexport type PropertyFilterCreatorProps = {\n fields: PropertyFilterField[];\n tokens: PropertyFilterToken[];\n onTokensChange: (tokens: PropertyFilterToken[]) => void;\n label?: string;\n disabled?: boolean;\n /** Size passed through to the trigger Button. Defaults to 'md'. */\n size?: ButtonProps['size'];\n /**\n * Called when the user picks a text (id-style) field. Consumers are expected\n * to render a pending applied-filter pill with an active input so the user\n * can type the value inline instead of in this popover.\n */\n onStartTextFilter?: (fieldId: string) => void;\n /**\n * Field ids hidden from the Add Filter dropdown. Use to prevent users from\n * recreating a filter that an upstream context already owns (e.g. the agent\n * id when viewing the agent-scoped traces tab).\n */\n hiddenFieldIds?: readonly string[];\n};\n\n/**\n * Minimal Linear-style filter creator: a `+ Filter` button whose popover walks\n * the user through property → value → commit. For id-style text fields, the\n * picker closes immediately and the applied-filter pill owns the input. For\n * `pick-multi` fields (e.g. Root Entity Name) hovering the item opens a\n * separate side popover with checkboxes — each check adds its own applied\n * filter and the main popover stays open so users can pick many.\n */\nexport function PropertyFilterCreator({\n fields,\n tokens,\n onTokensChange,\n label = 'Add filter',\n disabled,\n size,\n onStartTextFilter,\n hiddenFieldIds,\n}: PropertyFilterCreatorProps) {\n const visibleFields = useMemo(() => {\n if (!hiddenFieldIds || hiddenFieldIds.length === 0) return fields;\n const hidden = new Set(hiddenFieldIds);\n return fields.filter(f => !hidden.has(f.id));\n }, [fields, hiddenFieldIds]);\n const [open, setOpen] = useState(false);\n const [fieldId, setFieldId] = useState<string | undefined>();\n const [multiValue, setMultiValue] = useState<string[]>([]);\n const [error, setError] = useState<string | undefined>();\n // Single source of truth for which pick-multi side panel is open. Opens only\n // via explicit click/keyboard press on the menu item — no hover/focus\n // auto-open (was too flicker-prone).\n const [openPickMultiFieldId, setOpenPickMultiFieldId] = useState<string | undefined>();\n\n // When the user picks a text field we close this popover and hand off focus\n // to the newly-created pill's input — prevent Radix from returning focus to\n // the trigger button in that case.\n const skipCloseFocusRef = useRef(false);\n\n const togglePickMulti = useCallback((id: string) => {\n setOpenPickMultiFieldId(current => (current === id ? undefined : id));\n }, []);\n const closePickMulti = useCallback(() => setOpenPickMultiFieldId(undefined), []);\n\n useEffect(() => {\n if (!open) setOpenPickMultiFieldId(undefined);\n }, [open]);\n\n const selectedField = useMemo(() => visibleFields.find(f => f.id === fieldId), [visibleFields, fieldId]);\n // Only single-use kinds (text, multi-select) count as \"used\". `pick-multi`\n // allows multiple tokens with the same fieldId.\n const singleUseFieldIds = useMemo(() => {\n const ids = new Set<string>();\n for (const token of tokens) {\n const field = fields.find(f => f.id === token.fieldId);\n if (field && field.kind !== 'pick-multi') ids.add(token.fieldId);\n }\n return ids;\n }, [tokens, fields]);\n\n const reset = useCallback(() => {\n setFieldId(undefined);\n setMultiValue([]);\n setError(undefined);\n }, []);\n\n useEffect(() => {\n if (!open) reset();\n }, [open, reset]);\n\n /**\n * Replace whatever token exists for `fieldId` with the given value. Used by\n * both single-select (radio) and multi-select (checkbox) pick-multi panels.\n * An empty list means nothing is selected, which removes the token here —\n * unlike the applied pill, where the filter stays on in a neutral state.\n */\n const replacePickMultiToken = useCallback(\n (fieldId: string, value: string | string[]) => {\n const existingIndex = tokens.findIndex(t => t.fieldId === fieldId);\n\n if (Array.isArray(value) && value.length === 0) {\n if (existingIndex === -1) return;\n onTokensChange(tokens.filter((_, i) => i !== existingIndex));\n return;\n }\n\n if (existingIndex === -1) {\n onTokensChange([...tokens, { fieldId, value }]);\n return;\n }\n\n const nextTokens = [...tokens];\n nextTokens[existingIndex] = { fieldId, value };\n onTokensChange(nextTokens);\n },\n [onTokensChange, tokens],\n );\n\n const commit = useCallback(() => {\n if (!selectedField) {\n setError('Choose a property first.');\n return;\n }\n if (singleUseFieldIds.has(selectedField.id)) {\n setError(`Remove the existing ${selectedField.label} filter before adding another.`);\n return;\n }\n if (multiValue.length === 0) {\n setError(`Choose at least one ${selectedField.label.toLowerCase()} value.`);\n return;\n }\n onTokensChange([...tokens, { fieldId: selectedField.id, value: multiValue }]);\n setOpen(false);\n }, [multiValue, onTokensChange, selectedField, singleUseFieldIds, tokens]);\n\n return (\n <Popover open={open} onOpenChange={setOpen}>\n <PopoverTrigger asChild>\n <Button size={size} disabled={disabled} icon={<ListFilterPlusIcon />}>\n {label}\n </Button>\n </PopoverTrigger>\n <PopoverContent\n align=\"start\"\n sideOffset={MENU_SIDE_OFFSET}\n className={cn('w-64', selectedField ? 'p-3' : 'p-1')}\n initialFocus={false}\n finalFocus={() => {\n if (skipCloseFocusRef.current) {\n skipCloseFocusRef.current = false;\n return false;\n }\n return true;\n }}\n >\n <div className={cn('grid', selectedField && 'gap-3')}>\n {selectedField && (\n <div className=\"flex items-center gap-2\">\n <button\n type=\"button\"\n aria-label=\"Back to properties\"\n className={cn(quietTextHover, controlStateColorTransition)}\n onClick={reset}\n >\n <ArrowLeftIcon className=\"size-4\" />\n </button>\n <FilterIcon className=\"size-4 shrink-0 text-muted-foreground\" />\n <Txt as=\"span\" variant=\"caption\" tone=\"muted\">{`${selectedField.label} · is`}</Txt>\n </div>\n )}\n\n {!selectedField && (\n <div\n role=\"menu\"\n className=\"max-h-[80dvh] overflow-auto\"\n onKeyDown={e => {\n if (e.key !== 'ArrowDown' && e.key !== 'ArrowUp' && e.key !== 'Home' && e.key !== 'End') return;\n const buttons = Array.from(\n e.currentTarget.querySelectorAll<HTMLButtonElement>('[data-filter-item]:not([disabled])'),\n );\n if (buttons.length === 0) return;\n e.preventDefault();\n const active = document.activeElement as HTMLElement | null;\n const current = buttons.findIndex(b => b === active);\n let next: number;\n if (e.key === 'Home') next = 0;\n else if (e.key === 'End') next = buttons.length - 1;\n else if (e.key === 'ArrowDown') next = current < 0 ? 0 : (current + 1) % buttons.length;\n else next = current <= 0 ? buttons.length - 1 : current - 1;\n buttons[next]?.focus();\n }}\n >\n <>\n {visibleFields.length > 0 ? (\n visibleFields.map(f => {\n const used = singleUseFieldIds.has(f.id);\n if (f.kind === 'pick-multi') {\n return (\n <PickMultiMenuItem\n key={f.id}\n field={f}\n tokens={tokens}\n onChange={replacePickMultiToken}\n open={openPickMultiFieldId === f.id}\n onToggle={togglePickMulti}\n onClose={closePickMulti}\n />\n );\n }\n return (\n <FilterMenuButton\n key={f.id}\n className={cn(menuItemButtonClass, 'group')}\n disabled={used}\n onClick={() => {\n setError(undefined);\n if (f.kind === 'text') {\n onTokensChange([...tokens, { fieldId: f.id, value: '' }]);\n onStartTextFilter?.(f.id);\n skipCloseFocusRef.current = true;\n setOpen(false);\n return;\n }\n setFieldId(f.id);\n }}\n >\n <span className=\"truncate\">{f.label}</span>\n {used ? (\n <span className=\"ml-auto text-muted-foreground\">In use</span>\n ) : (\n <span\n className={cn(\n menuItemTrailingIconClass,\n 'text-muted-foreground opacity-0 group-hover:opacity-100 group-focus:opacity-100',\n )}\n >\n <PlusIcon />\n </span>\n )}\n </FilterMenuButton>\n );\n })\n ) : (\n <div className={menuEmptyClass}>No matching property.</div>\n )}\n </>\n </div>\n )}\n\n {selectedField && (\n <Field invalid={Boolean(error)}>\n <Combobox\n multiple\n options={selectedField.options ?? []}\n value={multiValue}\n onValueChange={v => {\n setMultiValue(v);\n setError(undefined);\n }}\n placeholder={selectedField.placeholder ?? `Choose ${selectedField.label}`}\n searchPlaceholder={`Search ${selectedField.label.toLowerCase()}...`}\n emptyText={selectedField.emptyText ?? 'No option found.'}\n size=\"md\"\n aria-label={selectedField.label}\n />\n <FieldError>{error}</FieldError>\n </Field>\n )}\n\n {selectedField && (\n <div className=\"flex items-center justify-end gap-2\">\n <Button icon={<X />} variant=\"ghost\" size=\"md\" onClick={() => setOpen(false)}>\n Cancel\n </Button>\n <Button icon={<ListFilterPlus />} size=\"md\" onClick={commit}>\n Add filter\n </Button>\n </div>\n )}\n </div>\n </PopoverContent>\n </Popover>\n );\n}\n\ntype PickMultiField = Extract<PropertyFilterField, { kind: 'pick-multi' }>;\n\ntype PickMultiMenuItemProps = {\n field: PickMultiField;\n tokens: PropertyFilterToken[];\n onChange: (fieldId: string, value: string | string[]) => void;\n open: boolean;\n onToggle: (fieldId: string) => void;\n onClose: () => void;\n};\n\n/**\n * A property-picker menu item that opens a separate Radix popover (portaled to\n * the side) with a radio group (single-select) or checkbox list (multi-select,\n * `field.multi === true`). Open/close is driven by explicit click / keyboard\n * press; the panel only closes when the user clicks outside, presses Escape,\n * or clicks the row again to toggle it off.\n */\nfunction PickMultiMenuItem({ field, tokens, onChange, open, onToggle, onClose }: PickMultiMenuItemProps) {\n const contentRef = useRef<HTMLDivElement>(null);\n\n return (\n <Popover\n open={open}\n onOpenChange={next => {\n if (next) onToggle(field.id);\n else onClose();\n }}\n >\n <PopoverTrigger asChild>\n <FilterMenuButton\n className={menuItemButtonClass}\n onKeyDown={e => {\n if (e.key !== 'ArrowRight' && e.key !== 'ArrowLeft') return;\n if (!open) onToggle(field.id);\n e.preventDefault();\n requestAnimationFrame(() => {\n const first = contentRef.current?.querySelector<HTMLElement>(\n 'input, button, [tabindex]:not([tabindex=\"-1\"])',\n );\n first?.focus();\n });\n }}\n >\n {open && <ChevronRightIcon className=\"text-muted-foreground\" />}\n <span className=\"truncate\">{field.label}</span>\n {!open && (\n <span className={cn(menuItemTrailingIconClass, 'text-muted-foreground')}>\n <ChevronRightIcon />\n </span>\n )}\n </FilterMenuButton>\n </PopoverTrigger>\n <PopoverContent\n ref={contentRef}\n side=\"right\"\n align=\"start\"\n sideOffset={MENU_SIDE_OFFSET}\n className=\"w-64 p-0\"\n initialFocus={false}\n onKeyDown={e => {\n if (e.key !== 'ArrowDown' && e.key !== 'ArrowUp' && e.key !== 'Home' && e.key !== 'End') return;\n const items = Array.from(\n e.currentTarget.querySelectorAll<HTMLElement>('[data-pick-multi-item]:not([disabled])'),\n );\n if (items.length === 0) return;\n e.preventDefault();\n e.stopPropagation();\n const active = document.activeElement as HTMLElement | null;\n const current = items.findIndex(el => el === active);\n let next: number;\n if (e.key === 'Home') next = 0;\n else if (e.key === 'End') next = items.length - 1;\n else if (e.key === 'ArrowDown') next = current < 0 ? 0 : (current + 1) % items.length;\n else next = current <= 0 ? items.length - 1 : current - 1;\n items[next]?.focus();\n }}\n data-pick-multi-panel\n >\n <PickMultiPanel field={field} tokens={tokens} onChange={onChange} />\n </PopoverContent>\n </Popover>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"PropertyFilter.cjs.js","names":["forwardRef","useMemo","useState","useRef","useCallback","Popover","PopoverTrigger","Button","ListFilterPlusIcon","PopoverContent","cn","ArrowLeftIcon","FilterIcon","Txt","_Fragment","menuItemButtonClass","menuItemTrailingIconClass","PlusIcon","Field","Combobox","FieldError","X","ListFilterPlus","ChevronRightIcon","PickMultiPanel"],"sources":["../../src/ds/components/PropertyFilter/property-filter-creator.tsx"],"sourcesContent":["import {\n ArrowLeftIcon,\n ChevronRightIcon,\n FilterIcon,\n ListFilterPlusIcon,\n PlusIcon,\n ListFilterPlus,\n X,\n} from 'lucide-react';\nimport { forwardRef, useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport type { ButtonHTMLAttributes } from 'react';\nimport { PickMultiPanel } from './pick-multi-panel';\nimport type { PropertyFilterField, PropertyFilterToken } from './types';\nimport { Button } from '@/ds/components/Button/Button';\nimport type { ButtonProps } from '@/ds/components/Button/Button';\nimport { Combobox } from '@/ds/components/Combobox/combobox';\nimport { Field, FieldError } from '@/ds/components/Field';\nimport { Popover, PopoverContent, PopoverTrigger } from '@/ds/components/Popover/popover';\nimport { Txt } from '@/ds/components/Txt';\nimport {\n MENU_SIDE_OFFSET,\n menuEmptyClass,\n menuItemButtonClass,\n menuItemTrailingIconClass,\n} from '@/ds/primitives/menu-item';\nimport { controlStateColorTransition } from '@/ds/primitives/transitions';\nimport { quietTextHover } from '@/ds/primitives/typography';\nimport { cn } from '@/lib/utils';\n\n// Plain <button>s navigated with roving focus (not Base UI).\nconst FilterMenuButton = forwardRef<HTMLButtonElement, ButtonHTMLAttributes<HTMLButtonElement>>((props, ref) => (\n <button type=\"button\" role=\"menuitem\" data-filter-item=\"\" ref={ref} {...props} />\n));\nFilterMenuButton.displayName = 'FilterMenuButton';\n\nexport type PropertyFilterCreatorProps = {\n fields: PropertyFilterField[];\n tokens: PropertyFilterToken[];\n onTokensChange: (tokens: PropertyFilterToken[]) => void;\n label?: string;\n disabled?: boolean;\n /** Size passed through to the trigger Button. Defaults to 'md'. */\n size?: ButtonProps['size'];\n /**\n * Called when the user picks a text (id-style) field. Consumers are expected\n * to render a pending applied-filter pill with an active input so the user\n * can type the value inline instead of in this popover.\n */\n onStartTextFilter?: (fieldId: string) => void;\n /**\n * Field ids hidden from the Add Filter dropdown. Use to prevent users from\n * recreating a filter that an upstream context already owns (e.g. the agent\n * id when viewing the agent-scoped traces tab).\n */\n hiddenFieldIds?: readonly string[];\n};\n\n/**\n * Minimal Linear-style filter creator: a `+ Filter` button whose popover walks\n * the user through property → value → commit. For id-style text fields, the\n * picker closes immediately and the applied-filter pill owns the input. For\n * `pick-multi` fields (e.g. Root Entity Name) hovering the item opens a\n * separate side popover with checkboxes — each check adds its own applied\n * filter and the main popover stays open so users can pick many.\n */\nexport function PropertyFilterCreator({\n fields,\n tokens,\n onTokensChange,\n label = 'Add filter',\n disabled,\n size,\n onStartTextFilter,\n hiddenFieldIds,\n}: PropertyFilterCreatorProps) {\n const visibleFields = useMemo(() => {\n if (!hiddenFieldIds || hiddenFieldIds.length === 0) return fields;\n const hidden = new Set(hiddenFieldIds);\n return fields.filter(f => !hidden.has(f.id));\n }, [fields, hiddenFieldIds]);\n const [open, setOpen] = useState(false);\n const [fieldId, setFieldId] = useState<string | undefined>();\n const [multiValue, setMultiValue] = useState<string[]>([]);\n const [error, setError] = useState<string | undefined>();\n // Single source of truth for which pick-multi side panel is open. Opens only\n // via explicit click/keyboard press on the menu item — no hover/focus\n // auto-open (was too flicker-prone).\n const [openPickMultiFieldId, setOpenPickMultiFieldId] = useState<string | undefined>();\n\n // When the user picks a text field we close this popover and hand off focus\n // to the newly-created pill's input — prevent Radix from returning focus to\n // the trigger button in that case.\n const skipCloseFocusRef = useRef(false);\n\n const togglePickMulti = useCallback((id: string) => {\n setOpenPickMultiFieldId(current => (current === id ? undefined : id));\n }, []);\n const closePickMulti = useCallback(() => setOpenPickMultiFieldId(undefined), []);\n\n useEffect(() => {\n if (!open) setOpenPickMultiFieldId(undefined);\n }, [open]);\n\n const selectedField = useMemo(() => visibleFields.find(f => f.id === fieldId), [visibleFields, fieldId]);\n // Only single-use kinds (text, multi-select) count as \"used\". `pick-multi`\n // allows multiple tokens with the same fieldId.\n const singleUseFieldIds = useMemo(() => {\n const ids = new Set<string>();\n for (const token of tokens) {\n const field = fields.find(f => f.id === token.fieldId);\n if (field && field.kind !== 'pick-multi') ids.add(token.fieldId);\n }\n return ids;\n }, [tokens, fields]);\n\n const reset = useCallback(() => {\n setFieldId(undefined);\n setMultiValue([]);\n setError(undefined);\n }, []);\n\n useEffect(() => {\n if (!open) reset();\n }, [open, reset]);\n\n /**\n * Replace whatever token exists for `fieldId` with the given value. Used by\n * both single-select (radio) and multi-select (checkbox) pick-multi panels.\n * An empty list means nothing is selected, which removes the token here —\n * unlike the applied pill, where the filter stays on in a neutral state.\n */\n const replacePickMultiToken = useCallback(\n (fieldId: string, value: string | string[]) => {\n const existingIndex = tokens.findIndex(t => t.fieldId === fieldId);\n\n if (Array.isArray(value) && value.length === 0) {\n if (existingIndex === -1) return;\n onTokensChange(tokens.filter((_, i) => i !== existingIndex));\n return;\n }\n\n if (existingIndex === -1) {\n onTokensChange([...tokens, { fieldId, value }]);\n return;\n }\n\n const nextTokens = [...tokens];\n nextTokens[existingIndex] = { fieldId, value };\n onTokensChange(nextTokens);\n },\n [onTokensChange, tokens],\n );\n\n const commit = useCallback(() => {\n if (!selectedField) {\n setError('Choose a property first.');\n return;\n }\n if (singleUseFieldIds.has(selectedField.id)) {\n setError(`Remove the existing ${selectedField.label} filter before adding another.`);\n return;\n }\n if (multiValue.length === 0) {\n setError(`Choose at least one ${selectedField.label.toLowerCase()} value.`);\n return;\n }\n onTokensChange([...tokens, { fieldId: selectedField.id, value: multiValue }]);\n setOpen(false);\n }, [multiValue, onTokensChange, selectedField, singleUseFieldIds, tokens]);\n\n return (\n <Popover open={open} onOpenChange={setOpen}>\n <PopoverTrigger asChild>\n <Button size={size} disabled={disabled} icon={<ListFilterPlusIcon />}>\n {label}\n </Button>\n </PopoverTrigger>\n <PopoverContent\n align=\"start\"\n sideOffset={MENU_SIDE_OFFSET}\n className={cn('w-64', selectedField ? 'p-3' : 'p-1')}\n initialFocus={false}\n finalFocus={() => {\n if (skipCloseFocusRef.current) {\n skipCloseFocusRef.current = false;\n return false;\n }\n return true;\n }}\n >\n <div className={cn('grid', selectedField && 'gap-3')}>\n {selectedField && (\n <div className=\"flex items-center gap-2\">\n <button\n type=\"button\"\n aria-label=\"Back to properties\"\n className={cn(quietTextHover, controlStateColorTransition)}\n onClick={reset}\n >\n <ArrowLeftIcon className=\"size-4\" />\n </button>\n <FilterIcon className=\"size-4 shrink-0 text-muted-foreground\" />\n <Txt as=\"span\" variant=\"caption\" tone=\"muted\">{`${selectedField.label} · is`}</Txt>\n </div>\n )}\n\n {!selectedField && (\n <div\n role=\"menu\"\n className=\"max-h-[80dvh] overflow-auto\"\n onKeyDown={e => {\n if (e.key !== 'ArrowDown' && e.key !== 'ArrowUp' && e.key !== 'Home' && e.key !== 'End') return;\n const buttons = Array.from(\n e.currentTarget.querySelectorAll<HTMLButtonElement>('[data-filter-item]:not([disabled])'),\n );\n if (buttons.length === 0) return;\n e.preventDefault();\n const active = document.activeElement as HTMLElement | null;\n const current = buttons.findIndex(b => b === active);\n let next: number;\n if (e.key === 'Home') next = 0;\n else if (e.key === 'End') next = buttons.length - 1;\n else if (e.key === 'ArrowDown') next = current < 0 ? 0 : (current + 1) % buttons.length;\n else next = current <= 0 ? buttons.length - 1 : current - 1;\n buttons[next]?.focus();\n }}\n >\n <>\n {visibleFields.length > 0 ? (\n visibleFields.map(f => {\n const used = singleUseFieldIds.has(f.id);\n if (f.kind === 'pick-multi') {\n return (\n <PickMultiMenuItem\n key={f.id}\n field={f}\n tokens={tokens}\n onChange={replacePickMultiToken}\n open={openPickMultiFieldId === f.id}\n onToggle={togglePickMulti}\n onClose={closePickMulti}\n />\n );\n }\n return (\n <FilterMenuButton\n key={f.id}\n className={cn(menuItemButtonClass, 'group')}\n disabled={used}\n onClick={() => {\n setError(undefined);\n if (f.kind === 'text') {\n onTokensChange([...tokens, { fieldId: f.id, value: '' }]);\n onStartTextFilter?.(f.id);\n skipCloseFocusRef.current = true;\n setOpen(false);\n return;\n }\n setFieldId(f.id);\n }}\n >\n <span className=\"truncate\">{f.label}</span>\n {used ? (\n <span className=\"ml-auto text-muted-foreground\">In use</span>\n ) : (\n <span\n className={cn(\n menuItemTrailingIconClass,\n 'text-muted-foreground opacity-0 group-hover:opacity-100 group-focus:opacity-100',\n )}\n >\n <PlusIcon />\n </span>\n )}\n </FilterMenuButton>\n );\n })\n ) : (\n <div className={menuEmptyClass}>No matching property.</div>\n )}\n </>\n </div>\n )}\n\n {selectedField && (\n <Field invalid={Boolean(error)}>\n <Combobox\n multiple\n options={selectedField.options ?? []}\n value={multiValue}\n onValueChange={v => {\n setMultiValue(v);\n setError(undefined);\n }}\n placeholder={selectedField.placeholder ?? `Choose ${selectedField.label}`}\n searchPlaceholder={`Search ${selectedField.label.toLowerCase()}`}\n emptyText={selectedField.emptyText ?? 'No option found.'}\n size=\"md\"\n aria-label={selectedField.label}\n />\n <FieldError>{error}</FieldError>\n </Field>\n )}\n\n {selectedField && (\n <div className=\"flex items-center justify-end gap-2\">\n <Button icon={<X />} variant=\"ghost\" size=\"md\" onClick={() => setOpen(false)}>\n Cancel\n </Button>\n <Button icon={<ListFilterPlus />} size=\"md\" onClick={commit}>\n Add filter\n </Button>\n </div>\n )}\n </div>\n </PopoverContent>\n </Popover>\n );\n}\n\ntype PickMultiField = Extract<PropertyFilterField, { kind: 'pick-multi' }>;\n\ntype PickMultiMenuItemProps = {\n field: PickMultiField;\n tokens: PropertyFilterToken[];\n onChange: (fieldId: string, value: string | string[]) => void;\n open: boolean;\n onToggle: (fieldId: string) => void;\n onClose: () => void;\n};\n\n/**\n * A property-picker menu item that opens a separate Radix popover (portaled to\n * the side) with a radio group (single-select) or checkbox list (multi-select,\n * `field.multi === true`). Open/close is driven by explicit click / keyboard\n * press; the panel only closes when the user clicks outside, presses Escape,\n * or clicks the row again to toggle it off.\n */\nfunction PickMultiMenuItem({ field, tokens, onChange, open, onToggle, onClose }: PickMultiMenuItemProps) {\n const contentRef = useRef<HTMLDivElement>(null);\n\n return (\n <Popover\n open={open}\n onOpenChange={next => {\n if (next) onToggle(field.id);\n else onClose();\n }}\n >\n <PopoverTrigger asChild>\n <FilterMenuButton\n className={menuItemButtonClass}\n onKeyDown={e => {\n if (e.key !== 'ArrowRight' && e.key !== 'ArrowLeft') return;\n if (!open) onToggle(field.id);\n e.preventDefault();\n requestAnimationFrame(() => {\n const first = contentRef.current?.querySelector<HTMLElement>(\n 'input, button, [tabindex]:not([tabindex=\"-1\"])',\n );\n first?.focus();\n });\n }}\n >\n {open && <ChevronRightIcon className=\"text-muted-foreground\" />}\n <span className=\"truncate\">{field.label}</span>\n {!open && (\n <span className={cn(menuItemTrailingIconClass, 'text-muted-foreground')}>\n <ChevronRightIcon />\n </span>\n )}\n </FilterMenuButton>\n </PopoverTrigger>\n <PopoverContent\n ref={contentRef}\n side=\"right\"\n align=\"start\"\n sideOffset={MENU_SIDE_OFFSET}\n className=\"w-64 p-0\"\n initialFocus={false}\n onKeyDown={e => {\n if (e.key !== 'ArrowDown' && e.key !== 'ArrowUp' && e.key !== 'Home' && e.key !== 'End') return;\n const items = Array.from(\n e.currentTarget.querySelectorAll<HTMLElement>('[data-pick-multi-item]:not([disabled])'),\n );\n if (items.length === 0) return;\n e.preventDefault();\n e.stopPropagation();\n const active = document.activeElement as HTMLElement | null;\n const current = items.findIndex(el => el === active);\n let next: number;\n if (e.key === 'Home') next = 0;\n else if (e.key === 'End') next = items.length - 1;\n else if (e.key === 'ArrowDown') next = current < 0 ? 0 : (current + 1) % items.length;\n else next = current <= 0 ? items.length - 1 : current - 1;\n items[next]?.focus();\n }}\n data-pick-multi-panel\n >\n <PickMultiPanel field={field} tokens={tokens} onChange={onChange} />\n </PopoverContent>\n </Popover>\n );\n}\n"],"mappings":"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"}
|
|
@@ -6,8 +6,8 @@ import "../primitives/typography.es.js";
|
|
|
6
6
|
import { t as Txt } from "../Txt-BM6TVV_c.js";
|
|
7
7
|
import { Field, FieldError } from "./Field.es.js";
|
|
8
8
|
import { i as PopoverTrigger, n as Popover, r as PopoverContent } from "../popover-CzHvTPk2.js";
|
|
9
|
-
import { t as Combobox } from "../combobox-
|
|
10
|
-
import { n as PickMultiPanel, r as PropertyFilterActions, t as PropertyFilterApplied } from "../property-filter-applied
|
|
9
|
+
import { t as Combobox } from "../combobox-D21no8t5.js";
|
|
10
|
+
import { n as PickMultiPanel, r as PropertyFilterActions, t as PropertyFilterApplied } from "../property-filter-applied--U5EZdaA.js";
|
|
11
11
|
import { forwardRef, useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
12
12
|
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
13
13
|
import { ArrowLeftIcon, ChevronRightIcon, FilterIcon, ListFilterPlus, ListFilterPlusIcon, PlusIcon, X } from "lucide-react";
|
|
@@ -232,7 +232,7 @@ function PropertyFilterCreator({ fields, tokens, onTokensChange, label = "Add fi
|
|
|
232
232
|
setError(void 0);
|
|
233
233
|
},
|
|
234
234
|
placeholder: selectedField.placeholder ?? `Choose ${selectedField.label}`,
|
|
235
|
-
searchPlaceholder: `Search ${selectedField.label.toLowerCase()}
|
|
235
|
+
searchPlaceholder: `Search ${selectedField.label.toLowerCase()}`,
|
|
236
236
|
emptyText: selectedField.emptyText ?? "No option found.",
|
|
237
237
|
size: "md",
|
|
238
238
|
"aria-label": selectedField.label
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PropertyFilter.es.js","names":["_Fragment"],"sources":["../../src/ds/components/PropertyFilter/property-filter-creator.tsx"],"sourcesContent":["import {\n ArrowLeftIcon,\n ChevronRightIcon,\n FilterIcon,\n ListFilterPlusIcon,\n PlusIcon,\n ListFilterPlus,\n X,\n} from 'lucide-react';\nimport { forwardRef, useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport type { ButtonHTMLAttributes } from 'react';\nimport { PickMultiPanel } from './pick-multi-panel';\nimport type { PropertyFilterField, PropertyFilterToken } from './types';\nimport { Button } from '@/ds/components/Button/Button';\nimport type { ButtonProps } from '@/ds/components/Button/Button';\nimport { Combobox } from '@/ds/components/Combobox/combobox';\nimport { Field, FieldError } from '@/ds/components/Field';\nimport { Popover, PopoverContent, PopoverTrigger } from '@/ds/components/Popover/popover';\nimport { Txt } from '@/ds/components/Txt';\nimport {\n MENU_SIDE_OFFSET,\n menuEmptyClass,\n menuItemButtonClass,\n menuItemTrailingIconClass,\n} from '@/ds/primitives/menu-item';\nimport { controlStateColorTransition } from '@/ds/primitives/transitions';\nimport { quietTextHover } from '@/ds/primitives/typography';\nimport { cn } from '@/lib/utils';\n\n// Plain <button>s navigated with roving focus (not Base UI).\nconst FilterMenuButton = forwardRef<HTMLButtonElement, ButtonHTMLAttributes<HTMLButtonElement>>((props, ref) => (\n <button type=\"button\" role=\"menuitem\" data-filter-item=\"\" ref={ref} {...props} />\n));\nFilterMenuButton.displayName = 'FilterMenuButton';\n\nexport type PropertyFilterCreatorProps = {\n fields: PropertyFilterField[];\n tokens: PropertyFilterToken[];\n onTokensChange: (tokens: PropertyFilterToken[]) => void;\n label?: string;\n disabled?: boolean;\n /** Size passed through to the trigger Button. Defaults to 'md'. */\n size?: ButtonProps['size'];\n /**\n * Called when the user picks a text (id-style) field. Consumers are expected\n * to render a pending applied-filter pill with an active input so the user\n * can type the value inline instead of in this popover.\n */\n onStartTextFilter?: (fieldId: string) => void;\n /**\n * Field ids hidden from the Add Filter dropdown. Use to prevent users from\n * recreating a filter that an upstream context already owns (e.g. the agent\n * id when viewing the agent-scoped traces tab).\n */\n hiddenFieldIds?: readonly string[];\n};\n\n/**\n * Minimal Linear-style filter creator: a `+ Filter` button whose popover walks\n * the user through property → value → commit. For id-style text fields, the\n * picker closes immediately and the applied-filter pill owns the input. For\n * `pick-multi` fields (e.g. Root Entity Name) hovering the item opens a\n * separate side popover with checkboxes — each check adds its own applied\n * filter and the main popover stays open so users can pick many.\n */\nexport function PropertyFilterCreator({\n fields,\n tokens,\n onTokensChange,\n label = 'Add filter',\n disabled,\n size,\n onStartTextFilter,\n hiddenFieldIds,\n}: PropertyFilterCreatorProps) {\n const visibleFields = useMemo(() => {\n if (!hiddenFieldIds || hiddenFieldIds.length === 0) return fields;\n const hidden = new Set(hiddenFieldIds);\n return fields.filter(f => !hidden.has(f.id));\n }, [fields, hiddenFieldIds]);\n const [open, setOpen] = useState(false);\n const [fieldId, setFieldId] = useState<string | undefined>();\n const [multiValue, setMultiValue] = useState<string[]>([]);\n const [error, setError] = useState<string | undefined>();\n // Single source of truth for which pick-multi side panel is open. Opens only\n // via explicit click/keyboard press on the menu item — no hover/focus\n // auto-open (was too flicker-prone).\n const [openPickMultiFieldId, setOpenPickMultiFieldId] = useState<string | undefined>();\n\n // When the user picks a text field we close this popover and hand off focus\n // to the newly-created pill's input — prevent Radix from returning focus to\n // the trigger button in that case.\n const skipCloseFocusRef = useRef(false);\n\n const togglePickMulti = useCallback((id: string) => {\n setOpenPickMultiFieldId(current => (current === id ? undefined : id));\n }, []);\n const closePickMulti = useCallback(() => setOpenPickMultiFieldId(undefined), []);\n\n useEffect(() => {\n if (!open) setOpenPickMultiFieldId(undefined);\n }, [open]);\n\n const selectedField = useMemo(() => visibleFields.find(f => f.id === fieldId), [visibleFields, fieldId]);\n // Only single-use kinds (text, multi-select) count as \"used\". `pick-multi`\n // allows multiple tokens with the same fieldId.\n const singleUseFieldIds = useMemo(() => {\n const ids = new Set<string>();\n for (const token of tokens) {\n const field = fields.find(f => f.id === token.fieldId);\n if (field && field.kind !== 'pick-multi') ids.add(token.fieldId);\n }\n return ids;\n }, [tokens, fields]);\n\n const reset = useCallback(() => {\n setFieldId(undefined);\n setMultiValue([]);\n setError(undefined);\n }, []);\n\n useEffect(() => {\n if (!open) reset();\n }, [open, reset]);\n\n /**\n * Replace whatever token exists for `fieldId` with the given value. Used by\n * both single-select (radio) and multi-select (checkbox) pick-multi panels.\n * An empty list means nothing is selected, which removes the token here —\n * unlike the applied pill, where the filter stays on in a neutral state.\n */\n const replacePickMultiToken = useCallback(\n (fieldId: string, value: string | string[]) => {\n const existingIndex = tokens.findIndex(t => t.fieldId === fieldId);\n\n if (Array.isArray(value) && value.length === 0) {\n if (existingIndex === -1) return;\n onTokensChange(tokens.filter((_, i) => i !== existingIndex));\n return;\n }\n\n if (existingIndex === -1) {\n onTokensChange([...tokens, { fieldId, value }]);\n return;\n }\n\n const nextTokens = [...tokens];\n nextTokens[existingIndex] = { fieldId, value };\n onTokensChange(nextTokens);\n },\n [onTokensChange, tokens],\n );\n\n const commit = useCallback(() => {\n if (!selectedField) {\n setError('Choose a property first.');\n return;\n }\n if (singleUseFieldIds.has(selectedField.id)) {\n setError(`Remove the existing ${selectedField.label} filter before adding another.`);\n return;\n }\n if (multiValue.length === 0) {\n setError(`Choose at least one ${selectedField.label.toLowerCase()} value.`);\n return;\n }\n onTokensChange([...tokens, { fieldId: selectedField.id, value: multiValue }]);\n setOpen(false);\n }, [multiValue, onTokensChange, selectedField, singleUseFieldIds, tokens]);\n\n return (\n <Popover open={open} onOpenChange={setOpen}>\n <PopoverTrigger asChild>\n <Button size={size} disabled={disabled} icon={<ListFilterPlusIcon />}>\n {label}\n </Button>\n </PopoverTrigger>\n <PopoverContent\n align=\"start\"\n sideOffset={MENU_SIDE_OFFSET}\n className={cn('w-64', selectedField ? 'p-3' : 'p-1')}\n initialFocus={false}\n finalFocus={() => {\n if (skipCloseFocusRef.current) {\n skipCloseFocusRef.current = false;\n return false;\n }\n return true;\n }}\n >\n <div className={cn('grid', selectedField && 'gap-3')}>\n {selectedField && (\n <div className=\"flex items-center gap-2\">\n <button\n type=\"button\"\n aria-label=\"Back to properties\"\n className={cn(quietTextHover, controlStateColorTransition)}\n onClick={reset}\n >\n <ArrowLeftIcon className=\"size-4\" />\n </button>\n <FilterIcon className=\"size-4 shrink-0 text-muted-foreground\" />\n <Txt as=\"span\" variant=\"caption\" tone=\"muted\">{`${selectedField.label} · is`}</Txt>\n </div>\n )}\n\n {!selectedField && (\n <div\n role=\"menu\"\n className=\"max-h-[80dvh] overflow-auto\"\n onKeyDown={e => {\n if (e.key !== 'ArrowDown' && e.key !== 'ArrowUp' && e.key !== 'Home' && e.key !== 'End') return;\n const buttons = Array.from(\n e.currentTarget.querySelectorAll<HTMLButtonElement>('[data-filter-item]:not([disabled])'),\n );\n if (buttons.length === 0) return;\n e.preventDefault();\n const active = document.activeElement as HTMLElement | null;\n const current = buttons.findIndex(b => b === active);\n let next: number;\n if (e.key === 'Home') next = 0;\n else if (e.key === 'End') next = buttons.length - 1;\n else if (e.key === 'ArrowDown') next = current < 0 ? 0 : (current + 1) % buttons.length;\n else next = current <= 0 ? buttons.length - 1 : current - 1;\n buttons[next]?.focus();\n }}\n >\n <>\n {visibleFields.length > 0 ? (\n visibleFields.map(f => {\n const used = singleUseFieldIds.has(f.id);\n if (f.kind === 'pick-multi') {\n return (\n <PickMultiMenuItem\n key={f.id}\n field={f}\n tokens={tokens}\n onChange={replacePickMultiToken}\n open={openPickMultiFieldId === f.id}\n onToggle={togglePickMulti}\n onClose={closePickMulti}\n />\n );\n }\n return (\n <FilterMenuButton\n key={f.id}\n className={cn(menuItemButtonClass, 'group')}\n disabled={used}\n onClick={() => {\n setError(undefined);\n if (f.kind === 'text') {\n onTokensChange([...tokens, { fieldId: f.id, value: '' }]);\n onStartTextFilter?.(f.id);\n skipCloseFocusRef.current = true;\n setOpen(false);\n return;\n }\n setFieldId(f.id);\n }}\n >\n <span className=\"truncate\">{f.label}</span>\n {used ? (\n <span className=\"ml-auto text-muted-foreground\">In use</span>\n ) : (\n <span\n className={cn(\n menuItemTrailingIconClass,\n 'text-muted-foreground opacity-0 group-hover:opacity-100 group-focus:opacity-100',\n )}\n >\n <PlusIcon />\n </span>\n )}\n </FilterMenuButton>\n );\n })\n ) : (\n <div className={menuEmptyClass}>No matching property.</div>\n )}\n </>\n </div>\n )}\n\n {selectedField && (\n <Field invalid={Boolean(error)}>\n <Combobox\n multiple\n options={selectedField.options ?? []}\n value={multiValue}\n onValueChange={v => {\n setMultiValue(v);\n setError(undefined);\n }}\n placeholder={selectedField.placeholder ?? `Choose ${selectedField.label}`}\n searchPlaceholder={`Search ${selectedField.label.toLowerCase()}...`}\n emptyText={selectedField.emptyText ?? 'No option found.'}\n size=\"md\"\n aria-label={selectedField.label}\n />\n <FieldError>{error}</FieldError>\n </Field>\n )}\n\n {selectedField && (\n <div className=\"flex items-center justify-end gap-2\">\n <Button icon={<X />} variant=\"ghost\" size=\"md\" onClick={() => setOpen(false)}>\n Cancel\n </Button>\n <Button icon={<ListFilterPlus />} size=\"md\" onClick={commit}>\n Add filter\n </Button>\n </div>\n )}\n </div>\n </PopoverContent>\n </Popover>\n );\n}\n\ntype PickMultiField = Extract<PropertyFilterField, { kind: 'pick-multi' }>;\n\ntype PickMultiMenuItemProps = {\n field: PickMultiField;\n tokens: PropertyFilterToken[];\n onChange: (fieldId: string, value: string | string[]) => void;\n open: boolean;\n onToggle: (fieldId: string) => void;\n onClose: () => void;\n};\n\n/**\n * A property-picker menu item that opens a separate Radix popover (portaled to\n * the side) with a radio group (single-select) or checkbox list (multi-select,\n * `field.multi === true`). Open/close is driven by explicit click / keyboard\n * press; the panel only closes when the user clicks outside, presses Escape,\n * or clicks the row again to toggle it off.\n */\nfunction PickMultiMenuItem({ field, tokens, onChange, open, onToggle, onClose }: PickMultiMenuItemProps) {\n const contentRef = useRef<HTMLDivElement>(null);\n\n return (\n <Popover\n open={open}\n onOpenChange={next => {\n if (next) onToggle(field.id);\n else onClose();\n }}\n >\n <PopoverTrigger asChild>\n <FilterMenuButton\n className={menuItemButtonClass}\n onKeyDown={e => {\n if (e.key !== 'ArrowRight' && e.key !== 'ArrowLeft') return;\n if (!open) onToggle(field.id);\n e.preventDefault();\n requestAnimationFrame(() => {\n const first = contentRef.current?.querySelector<HTMLElement>(\n 'input, button, [tabindex]:not([tabindex=\"-1\"])',\n );\n first?.focus();\n });\n }}\n >\n {open && <ChevronRightIcon className=\"text-muted-foreground\" />}\n <span className=\"truncate\">{field.label}</span>\n {!open && (\n <span className={cn(menuItemTrailingIconClass, 'text-muted-foreground')}>\n <ChevronRightIcon />\n </span>\n )}\n </FilterMenuButton>\n </PopoverTrigger>\n <PopoverContent\n ref={contentRef}\n side=\"right\"\n align=\"start\"\n sideOffset={MENU_SIDE_OFFSET}\n className=\"w-64 p-0\"\n initialFocus={false}\n onKeyDown={e => {\n if (e.key !== 'ArrowDown' && e.key !== 'ArrowUp' && e.key !== 'Home' && e.key !== 'End') return;\n const items = Array.from(\n e.currentTarget.querySelectorAll<HTMLElement>('[data-pick-multi-item]:not([disabled])'),\n );\n if (items.length === 0) return;\n e.preventDefault();\n e.stopPropagation();\n const active = document.activeElement as HTMLElement | null;\n const current = items.findIndex(el => el === active);\n let next: number;\n if (e.key === 'Home') next = 0;\n else if (e.key === 'End') next = items.length - 1;\n else if (e.key === 'ArrowDown') next = current < 0 ? 0 : (current + 1) % items.length;\n else next = current <= 0 ? items.length - 1 : current - 1;\n items[next]?.focus();\n }}\n data-pick-multi-panel\n >\n <PickMultiPanel field={field} tokens={tokens} onChange={onChange} />\n </PopoverContent>\n </Popover>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"PropertyFilter.es.js","names":["_Fragment"],"sources":["../../src/ds/components/PropertyFilter/property-filter-creator.tsx"],"sourcesContent":["import {\n ArrowLeftIcon,\n ChevronRightIcon,\n FilterIcon,\n ListFilterPlusIcon,\n PlusIcon,\n ListFilterPlus,\n X,\n} from 'lucide-react';\nimport { forwardRef, useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport type { ButtonHTMLAttributes } from 'react';\nimport { PickMultiPanel } from './pick-multi-panel';\nimport type { PropertyFilterField, PropertyFilterToken } from './types';\nimport { Button } from '@/ds/components/Button/Button';\nimport type { ButtonProps } from '@/ds/components/Button/Button';\nimport { Combobox } from '@/ds/components/Combobox/combobox';\nimport { Field, FieldError } from '@/ds/components/Field';\nimport { Popover, PopoverContent, PopoverTrigger } from '@/ds/components/Popover/popover';\nimport { Txt } from '@/ds/components/Txt';\nimport {\n MENU_SIDE_OFFSET,\n menuEmptyClass,\n menuItemButtonClass,\n menuItemTrailingIconClass,\n} from '@/ds/primitives/menu-item';\nimport { controlStateColorTransition } from '@/ds/primitives/transitions';\nimport { quietTextHover } from '@/ds/primitives/typography';\nimport { cn } from '@/lib/utils';\n\n// Plain <button>s navigated with roving focus (not Base UI).\nconst FilterMenuButton = forwardRef<HTMLButtonElement, ButtonHTMLAttributes<HTMLButtonElement>>((props, ref) => (\n <button type=\"button\" role=\"menuitem\" data-filter-item=\"\" ref={ref} {...props} />\n));\nFilterMenuButton.displayName = 'FilterMenuButton';\n\nexport type PropertyFilterCreatorProps = {\n fields: PropertyFilterField[];\n tokens: PropertyFilterToken[];\n onTokensChange: (tokens: PropertyFilterToken[]) => void;\n label?: string;\n disabled?: boolean;\n /** Size passed through to the trigger Button. Defaults to 'md'. */\n size?: ButtonProps['size'];\n /**\n * Called when the user picks a text (id-style) field. Consumers are expected\n * to render a pending applied-filter pill with an active input so the user\n * can type the value inline instead of in this popover.\n */\n onStartTextFilter?: (fieldId: string) => void;\n /**\n * Field ids hidden from the Add Filter dropdown. Use to prevent users from\n * recreating a filter that an upstream context already owns (e.g. the agent\n * id when viewing the agent-scoped traces tab).\n */\n hiddenFieldIds?: readonly string[];\n};\n\n/**\n * Minimal Linear-style filter creator: a `+ Filter` button whose popover walks\n * the user through property → value → commit. For id-style text fields, the\n * picker closes immediately and the applied-filter pill owns the input. For\n * `pick-multi` fields (e.g. Root Entity Name) hovering the item opens a\n * separate side popover with checkboxes — each check adds its own applied\n * filter and the main popover stays open so users can pick many.\n */\nexport function PropertyFilterCreator({\n fields,\n tokens,\n onTokensChange,\n label = 'Add filter',\n disabled,\n size,\n onStartTextFilter,\n hiddenFieldIds,\n}: PropertyFilterCreatorProps) {\n const visibleFields = useMemo(() => {\n if (!hiddenFieldIds || hiddenFieldIds.length === 0) return fields;\n const hidden = new Set(hiddenFieldIds);\n return fields.filter(f => !hidden.has(f.id));\n }, [fields, hiddenFieldIds]);\n const [open, setOpen] = useState(false);\n const [fieldId, setFieldId] = useState<string | undefined>();\n const [multiValue, setMultiValue] = useState<string[]>([]);\n const [error, setError] = useState<string | undefined>();\n // Single source of truth for which pick-multi side panel is open. Opens only\n // via explicit click/keyboard press on the menu item — no hover/focus\n // auto-open (was too flicker-prone).\n const [openPickMultiFieldId, setOpenPickMultiFieldId] = useState<string | undefined>();\n\n // When the user picks a text field we close this popover and hand off focus\n // to the newly-created pill's input — prevent Radix from returning focus to\n // the trigger button in that case.\n const skipCloseFocusRef = useRef(false);\n\n const togglePickMulti = useCallback((id: string) => {\n setOpenPickMultiFieldId(current => (current === id ? undefined : id));\n }, []);\n const closePickMulti = useCallback(() => setOpenPickMultiFieldId(undefined), []);\n\n useEffect(() => {\n if (!open) setOpenPickMultiFieldId(undefined);\n }, [open]);\n\n const selectedField = useMemo(() => visibleFields.find(f => f.id === fieldId), [visibleFields, fieldId]);\n // Only single-use kinds (text, multi-select) count as \"used\". `pick-multi`\n // allows multiple tokens with the same fieldId.\n const singleUseFieldIds = useMemo(() => {\n const ids = new Set<string>();\n for (const token of tokens) {\n const field = fields.find(f => f.id === token.fieldId);\n if (field && field.kind !== 'pick-multi') ids.add(token.fieldId);\n }\n return ids;\n }, [tokens, fields]);\n\n const reset = useCallback(() => {\n setFieldId(undefined);\n setMultiValue([]);\n setError(undefined);\n }, []);\n\n useEffect(() => {\n if (!open) reset();\n }, [open, reset]);\n\n /**\n * Replace whatever token exists for `fieldId` with the given value. Used by\n * both single-select (radio) and multi-select (checkbox) pick-multi panels.\n * An empty list means nothing is selected, which removes the token here —\n * unlike the applied pill, where the filter stays on in a neutral state.\n */\n const replacePickMultiToken = useCallback(\n (fieldId: string, value: string | string[]) => {\n const existingIndex = tokens.findIndex(t => t.fieldId === fieldId);\n\n if (Array.isArray(value) && value.length === 0) {\n if (existingIndex === -1) return;\n onTokensChange(tokens.filter((_, i) => i !== existingIndex));\n return;\n }\n\n if (existingIndex === -1) {\n onTokensChange([...tokens, { fieldId, value }]);\n return;\n }\n\n const nextTokens = [...tokens];\n nextTokens[existingIndex] = { fieldId, value };\n onTokensChange(nextTokens);\n },\n [onTokensChange, tokens],\n );\n\n const commit = useCallback(() => {\n if (!selectedField) {\n setError('Choose a property first.');\n return;\n }\n if (singleUseFieldIds.has(selectedField.id)) {\n setError(`Remove the existing ${selectedField.label} filter before adding another.`);\n return;\n }\n if (multiValue.length === 0) {\n setError(`Choose at least one ${selectedField.label.toLowerCase()} value.`);\n return;\n }\n onTokensChange([...tokens, { fieldId: selectedField.id, value: multiValue }]);\n setOpen(false);\n }, [multiValue, onTokensChange, selectedField, singleUseFieldIds, tokens]);\n\n return (\n <Popover open={open} onOpenChange={setOpen}>\n <PopoverTrigger asChild>\n <Button size={size} disabled={disabled} icon={<ListFilterPlusIcon />}>\n {label}\n </Button>\n </PopoverTrigger>\n <PopoverContent\n align=\"start\"\n sideOffset={MENU_SIDE_OFFSET}\n className={cn('w-64', selectedField ? 'p-3' : 'p-1')}\n initialFocus={false}\n finalFocus={() => {\n if (skipCloseFocusRef.current) {\n skipCloseFocusRef.current = false;\n return false;\n }\n return true;\n }}\n >\n <div className={cn('grid', selectedField && 'gap-3')}>\n {selectedField && (\n <div className=\"flex items-center gap-2\">\n <button\n type=\"button\"\n aria-label=\"Back to properties\"\n className={cn(quietTextHover, controlStateColorTransition)}\n onClick={reset}\n >\n <ArrowLeftIcon className=\"size-4\" />\n </button>\n <FilterIcon className=\"size-4 shrink-0 text-muted-foreground\" />\n <Txt as=\"span\" variant=\"caption\" tone=\"muted\">{`${selectedField.label} · is`}</Txt>\n </div>\n )}\n\n {!selectedField && (\n <div\n role=\"menu\"\n className=\"max-h-[80dvh] overflow-auto\"\n onKeyDown={e => {\n if (e.key !== 'ArrowDown' && e.key !== 'ArrowUp' && e.key !== 'Home' && e.key !== 'End') return;\n const buttons = Array.from(\n e.currentTarget.querySelectorAll<HTMLButtonElement>('[data-filter-item]:not([disabled])'),\n );\n if (buttons.length === 0) return;\n e.preventDefault();\n const active = document.activeElement as HTMLElement | null;\n const current = buttons.findIndex(b => b === active);\n let next: number;\n if (e.key === 'Home') next = 0;\n else if (e.key === 'End') next = buttons.length - 1;\n else if (e.key === 'ArrowDown') next = current < 0 ? 0 : (current + 1) % buttons.length;\n else next = current <= 0 ? buttons.length - 1 : current - 1;\n buttons[next]?.focus();\n }}\n >\n <>\n {visibleFields.length > 0 ? (\n visibleFields.map(f => {\n const used = singleUseFieldIds.has(f.id);\n if (f.kind === 'pick-multi') {\n return (\n <PickMultiMenuItem\n key={f.id}\n field={f}\n tokens={tokens}\n onChange={replacePickMultiToken}\n open={openPickMultiFieldId === f.id}\n onToggle={togglePickMulti}\n onClose={closePickMulti}\n />\n );\n }\n return (\n <FilterMenuButton\n key={f.id}\n className={cn(menuItemButtonClass, 'group')}\n disabled={used}\n onClick={() => {\n setError(undefined);\n if (f.kind === 'text') {\n onTokensChange([...tokens, { fieldId: f.id, value: '' }]);\n onStartTextFilter?.(f.id);\n skipCloseFocusRef.current = true;\n setOpen(false);\n return;\n }\n setFieldId(f.id);\n }}\n >\n <span className=\"truncate\">{f.label}</span>\n {used ? (\n <span className=\"ml-auto text-muted-foreground\">In use</span>\n ) : (\n <span\n className={cn(\n menuItemTrailingIconClass,\n 'text-muted-foreground opacity-0 group-hover:opacity-100 group-focus:opacity-100',\n )}\n >\n <PlusIcon />\n </span>\n )}\n </FilterMenuButton>\n );\n })\n ) : (\n <div className={menuEmptyClass}>No matching property.</div>\n )}\n </>\n </div>\n )}\n\n {selectedField && (\n <Field invalid={Boolean(error)}>\n <Combobox\n multiple\n options={selectedField.options ?? []}\n value={multiValue}\n onValueChange={v => {\n setMultiValue(v);\n setError(undefined);\n }}\n placeholder={selectedField.placeholder ?? `Choose ${selectedField.label}`}\n searchPlaceholder={`Search ${selectedField.label.toLowerCase()}`}\n emptyText={selectedField.emptyText ?? 'No option found.'}\n size=\"md\"\n aria-label={selectedField.label}\n />\n <FieldError>{error}</FieldError>\n </Field>\n )}\n\n {selectedField && (\n <div className=\"flex items-center justify-end gap-2\">\n <Button icon={<X />} variant=\"ghost\" size=\"md\" onClick={() => setOpen(false)}>\n Cancel\n </Button>\n <Button icon={<ListFilterPlus />} size=\"md\" onClick={commit}>\n Add filter\n </Button>\n </div>\n )}\n </div>\n </PopoverContent>\n </Popover>\n );\n}\n\ntype PickMultiField = Extract<PropertyFilterField, { kind: 'pick-multi' }>;\n\ntype PickMultiMenuItemProps = {\n field: PickMultiField;\n tokens: PropertyFilterToken[];\n onChange: (fieldId: string, value: string | string[]) => void;\n open: boolean;\n onToggle: (fieldId: string) => void;\n onClose: () => void;\n};\n\n/**\n * A property-picker menu item that opens a separate Radix popover (portaled to\n * the side) with a radio group (single-select) or checkbox list (multi-select,\n * `field.multi === true`). Open/close is driven by explicit click / keyboard\n * press; the panel only closes when the user clicks outside, presses Escape,\n * or clicks the row again to toggle it off.\n */\nfunction PickMultiMenuItem({ field, tokens, onChange, open, onToggle, onClose }: PickMultiMenuItemProps) {\n const contentRef = useRef<HTMLDivElement>(null);\n\n return (\n <Popover\n open={open}\n onOpenChange={next => {\n if (next) onToggle(field.id);\n else onClose();\n }}\n >\n <PopoverTrigger asChild>\n <FilterMenuButton\n className={menuItemButtonClass}\n onKeyDown={e => {\n if (e.key !== 'ArrowRight' && e.key !== 'ArrowLeft') return;\n if (!open) onToggle(field.id);\n e.preventDefault();\n requestAnimationFrame(() => {\n const first = contentRef.current?.querySelector<HTMLElement>(\n 'input, button, [tabindex]:not([tabindex=\"-1\"])',\n );\n first?.focus();\n });\n }}\n >\n {open && <ChevronRightIcon className=\"text-muted-foreground\" />}\n <span className=\"truncate\">{field.label}</span>\n {!open && (\n <span className={cn(menuItemTrailingIconClass, 'text-muted-foreground')}>\n <ChevronRightIcon />\n </span>\n )}\n </FilterMenuButton>\n </PopoverTrigger>\n <PopoverContent\n ref={contentRef}\n side=\"right\"\n align=\"start\"\n sideOffset={MENU_SIDE_OFFSET}\n className=\"w-64 p-0\"\n initialFocus={false}\n onKeyDown={e => {\n if (e.key !== 'ArrowDown' && e.key !== 'ArrowUp' && e.key !== 'Home' && e.key !== 'End') return;\n const items = Array.from(\n e.currentTarget.querySelectorAll<HTMLElement>('[data-pick-multi-item]:not([disabled])'),\n );\n if (items.length === 0) return;\n e.preventDefault();\n e.stopPropagation();\n const active = document.activeElement as HTMLElement | null;\n const current = items.findIndex(el => el === active);\n let next: number;\n if (e.key === 'Home') next = 0;\n else if (e.key === 'End') next = items.length - 1;\n else if (e.key === 'ArrowDown') next = current < 0 ? 0 : (current + 1) % items.length;\n else next = current <= 0 ? items.length - 1 : current - 1;\n items[next]?.focus();\n }}\n data-pick-multi-panel\n >\n <PickMultiPanel field={field} tokens={tokens} onChange={onChange} />\n </PopoverContent>\n </Popover>\n );\n}\n"],"mappings":"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"}
|
|
@@ -9,7 +9,7 @@ const require_primitives_password_manager_autofill = require("../primitives/pass
|
|
|
9
9
|
const require_dropdown_menu = require("../dropdown-menu-BETTTPBB.cjs");
|
|
10
10
|
const require_context_menu = require("../context-menu-DTFPCyae.cjs");
|
|
11
11
|
const require_saved_view_schema = require("../saved-view-schema-DRJYELfK.cjs");
|
|
12
|
-
const require_filter_bar_chip = require("../filter-bar-chip-
|
|
12
|
+
const require_filter_bar_chip = require("../filter-bar-chip-Cg-UbIwP.cjs");
|
|
13
13
|
const require_components_HoverCard = require("./HoverCard.cjs.js");
|
|
14
14
|
let react = require("react");
|
|
15
15
|
let react_jsx_runtime = require("react/jsx-runtime");
|
|
@@ -8,7 +8,7 @@ import { passwordManagerOptOutProps } from "../primitives/password-manager-autof
|
|
|
8
8
|
import { t as DropdownMenu } from "../dropdown-menu-B4jY3J9e.js";
|
|
9
9
|
import { t as ContextMenu } from "../context-menu-Dv0NU0oM.js";
|
|
10
10
|
import { n as savedViewNameSchema, r as serializeSavedViews, t as parseSavedViews } from "../saved-view-schema-eJXlRRel.js";
|
|
11
|
-
import { o as FilterBarFieldLabel, u as formatValue } from "../filter-bar-chip-
|
|
11
|
+
import { o as FilterBarFieldLabel, u as formatValue } from "../filter-bar-chip-CABeKrtf.js";
|
|
12
12
|
import { HoverCard, HoverCardContent, HoverCardTrigger } from "./HoverCard.es.js";
|
|
13
13
|
import { VisuallyHidden } from "../primitives/visually-hidden.es.js";
|
|
14
14
|
import { Fragment, useRef, useState, useSyncExternalStore } from "react";
|
|
@@ -202,7 +202,7 @@ var SidebarMeter = (0, react.forwardRef)(function SidebarMeter({ label, value, s
|
|
|
202
202
|
"data-slot": "sidebar-meter",
|
|
203
203
|
"data-tone": tone,
|
|
204
204
|
"data-state": state,
|
|
205
|
-
className: require_utils.cn("relative isolate flex flex-col justify-center overflow-hidden rounded-lg border border-border bg-background px-3", href && "state-layer", className),
|
|
205
|
+
className: require_utils.cn("relative isolate flex flex-col justify-center overflow-hidden rounded-lg border border-border bg-background px-3", href && require_utils.cn("state-layer", "before:transition-none"), className),
|
|
206
206
|
style: { height: CARD_HEIGHT },
|
|
207
207
|
...props,
|
|
208
208
|
children: [
|
|
@@ -342,10 +342,10 @@ function SidebarHeader({ className, children, collapsedLogo, actions, ...props }
|
|
|
342
342
|
children: [collapsed && collapsedLogo ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
343
343
|
className: "group/collapsed-logo relative ml-0.5 grid size-9 shrink-0 place-items-center",
|
|
344
344
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
345
|
-
className: require_utils.cn(hold, "grid place-items-center
|
|
345
|
+
className: require_utils.cn(hold, "grid place-items-center [--sidebar-hold-opacity:1] group-focus-within/collapsed-logo:opacity-0 group-hover/sidebar:opacity-0"),
|
|
346
346
|
children: collapsedLogo
|
|
347
347
|
}), isMobile ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
348
|
-
className: require_utils.cn(hold, "absolute inset-0 grid place-items-center opacity-0
|
|
348
|
+
className: require_utils.cn(hold, "absolute inset-0 grid place-items-center opacity-0 [--sidebar-hold-opacity:0] group-hover/sidebar:opacity-100 focus-within:opacity-100"),
|
|
349
349
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SidebarTrigger, {})
|
|
350
350
|
})]
|
|
351
351
|
}) : children, actions]
|
|
@@ -411,7 +411,7 @@ function SidebarNavHeader({ children, icon, action, className, state: stateProp,
|
|
|
411
411
|
className: require_utils.cn("max-w-full min-w-0 flex-1 truncate text-column", icon ? "pl-2" : "pl-3", toneClassName),
|
|
412
412
|
children: href ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Link, {
|
|
413
413
|
href,
|
|
414
|
-
className: require_utils.cn("block min-w-0 truncate
|
|
414
|
+
className: require_utils.cn("block min-w-0 truncate", {
|
|
415
415
|
"hover:text-foreground": !isActive,
|
|
416
416
|
"text-foreground": isActive
|
|
417
417
|
}),
|
|
@@ -471,11 +471,11 @@ var nestedExpandedItemClasses = (level) => {
|
|
|
471
471
|
if (level === 2) return `gap-2 py-1 pr-3 pl-10 ${require_primitives_control_size.controlHeight.md}`;
|
|
472
472
|
return `gap-2 py-1 pr-3 pl-12 ${require_primitives_control_size.controlHeight.md}`;
|
|
473
473
|
};
|
|
474
|
-
var idleSurface = require_utils.cn("rounded-lg text-muted-foreground hover:text-foreground", require_primitives_raised_surface.surfaceStateLayerStyle);
|
|
474
|
+
var idleSurface = require_utils.cn("rounded-lg text-muted-foreground transition-none before:transition-none hover:text-foreground", require_primitives_raised_surface.surfaceStateLayerStyle);
|
|
475
475
|
var activeSurface = "bg-fill text-foreground";
|
|
476
476
|
var featuredSurface = require_utils.cn("my-2 border border-transparent bg-brand-green text-black hover:text-black hover:brightness-95");
|
|
477
477
|
var navRowSurfaceClasses = ({ isActive, isFeatured }) => require_utils.cn(idleSurface, isActive && activeSurface, isFeatured && featuredSurface);
|
|
478
|
-
var navItemLayoutClasses = ({ isCollapsed, level = 0, size }) => require_utils.cn(navItemVariants({ size }), "w-full justify-start",
|
|
478
|
+
var navItemLayoutClasses = ({ isCollapsed, level = 0, size }) => require_utils.cn(navItemVariants({ size }), "w-full justify-start", "[&_svg]:size-4 [&_svg]:shrink-0", require_primitives_transitions.focusRing, !isCollapsed && nestedExpandedItemClasses(level), isCollapsed && "gap-0 px-[13.5px] py-0");
|
|
479
479
|
var navItemClasses = ({ isActive, isCollapsed, isFeatured, level, size } = {}) => require_utils.cn(navItemLayoutClasses({
|
|
480
480
|
isCollapsed,
|
|
481
481
|
level,
|
|
@@ -625,7 +625,7 @@ function SidebarNavShowMore({ foldedCount, expanded, onExpandedChange, state: st
|
|
|
625
625
|
className: require_utils.cn(require_primitives_text.textStyle({
|
|
626
626
|
variant: "caption",
|
|
627
627
|
tone: "muted"
|
|
628
|
-
}), "self-start rounded-md pl-3 text-left hover:text-foreground", require_primitives_transitions.
|
|
628
|
+
}), "self-start rounded-md pl-3 text-left hover:text-foreground", require_primitives_transitions.focusRing, className),
|
|
629
629
|
...props,
|
|
630
630
|
children: expanded ? "Show less" : `Show ${foldedCount} more`
|
|
631
631
|
});
|
|
@@ -1177,7 +1177,7 @@ function SidebarPanel({ children, className, mobileMode = "drawer" }) {
|
|
|
1177
1177
|
onClick,
|
|
1178
1178
|
onKeyDown,
|
|
1179
1179
|
className: require_utils.cn("group absolute top-0 -right-1 z-10 h-full w-2 cursor-col-resize touch-none", "flex items-center justify-center", "focus-visible:outline-hidden"),
|
|
1180
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_primitives_resize_handle_indicator.ResizeHandleIndicator, { className: require_utils.cn("via-foreground/30 group-hover:opacity-100", "group-focus-visible:via-border-focus group-focus-visible:opacity-100", "in-data-[sidebar-gesture=active]:via-foreground/45 in-data-[sidebar-gesture=active]:opacity-100") })
|
|
1180
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_primitives_resize_handle_indicator.ResizeHandleIndicator, { className: require_utils.cn("via-foreground/30 transition-none group-hover:opacity-100", "group-focus-visible:via-border-focus group-focus-visible:opacity-100", "in-data-[sidebar-gesture=active]:via-foreground/45 in-data-[sidebar-gesture=active]:opacity-100") })
|
|
1181
1181
|
})]
|
|
1182
1182
|
});
|
|
1183
1183
|
}
|