import React from 'react'; import PropTypes from 'prop-types'; import { Heading, Divider } from '@splunk/react-ui/Menu'; import { SelectBaseChangeReason } from '@splunk/react-ui/SelectBase'; import { CompactPropsBase } from './Compact'; import Option from './Option'; import { ComponentProps } from '../utils/types'; /** @public */ type MultiselectFilterChangeHandler = (event: React.ChangeEvent | React.FocusEvent | React.MouseEvent | React.KeyboardEvent, data: { keyword: string; }) => void; /** @public */ type MultiselectChangeHandler = (event: React.MouseEvent | React.KeyboardEvent, data: { name?: string; reason?: SelectBaseChangeReason; values: (string | number | boolean)[]; }) => void; /** @public */ type MultiselectScrollBottomHandler = (event: React.UIEvent | React.KeyboardEvent | null) => void; interface MultiselectPropsBase { /** * Allow the user to add arbitrary values. */ allowNewValues?: boolean; animateLoading?: boolean; /** Append removes rounded borders and the border from the right side. */ append?: boolean; /** * When compact, options are shown as checkboxes and the input is a single line. This is * useful when placing the Multiselect in a horizontal bar, such as a filter. */ compact?: boolean; /** * `children` should be `Multiselect.Option`, `Multiselect.Heading`, or * `Multiselect.Divider`. */ children?: React.ReactNode; /** If true, this component will not handle filtering. The parent must update the * Options based on the onFilterChange value. * * Ignored in `compact` mode if the `filter` prop is provided. */ controlledFilter?: boolean; /** * The default placement of the dropdown menu. It might be rendered in a different direction * depending upon the space available. */ defaultPlacement?: 'above' | 'below' | 'vertical'; /** * Set this property instead of value to keep the value uncontrolled. */ defaultValues?: (string | number | boolean)[]; /** * The id of the description. When placed in a ControlGroup, this is automatically set to the * ControlGroup's help component. */ describedBy?: string; /** * Prevents user interaction and adds disabled styling. * * If set to `dimmed`, the component is able to receive focus. * If set to `disabled`, the component is unable to receive focus. */ disabled?: boolean | 'dimmed' | 'disabled'; /** * A React ref which is set to the DOM element when the component mounts, and null when it unmounts. */ elementRef?: React.Ref; /** Display as in an error. */ error?: boolean; /** * Determines whether to show the filter box. When true, the children are automatically * filtered based on the label. When controlled, the parent component must provide a * onFilterChange callback and update the children. * * Only supported when `compact=true`. */ filter?: boolean | 'controlled'; /** * The footer message can show additional information, such as a truncation message. */ footerMessage?: React.ReactNode; /** Make the control an inline block with variable width. */ inline?: boolean; /** * An id for the input, which may be necessary for accessibility, such as for aria * attributes. */ inputId?: string; /** * A React ref which is set to the input element when the component mounts and null when it unmounts. */ inputRef?: React.Ref; isLoadingOptions?: boolean; /** * The id of the label. When placed in a ControlGroup, this is automatically set to the * ControlGroup's label. */ labelledBy?: string; /** * The loading message to show when isLoadingOptions. */ loadingMessage?: React.ReactNode; /** * @private * Escape hatch override of the maximum number of values before the toggle label will truncate to `X items selected` */ maxLabelItems?: number; /** * Style properties to apply to the Menu. This is primarily used to override the width of * the menu should it need to be wider than the toggle Button. */ menuStyle?: React.CSSProperties; /** The name is returned with onChange events, which can be used to identify the * control when multiple controls share an onChange callback. */ name?: string; /** * The noOptionsMessage is shown when there are no children and it's not loading, such as when * there are no Options matching the filter. This can be customized to the type of content, * for example: "No matching dashboards". You can insert other content, such as an error message, or * communicate a minimum number of characters to enter to see results. */ noOptionsMessage?: React.ReactNode; /** * A callback to receive the change events. If values is set, this callback is required. * This must set the values prop to retain the change. * Supports custom selection behavior. */ onChange?: MultiselectChangeHandler; /** * A callback function invoked when the popover closes. */ onClose?: () => void; /** * A callback with the change event and value of the filter box. Providing this callback and * setting controlledFilter to true enables you to filter and update the children by other * criteria. */ onFilterChange?: MultiselectFilterChangeHandler; /** * A callback function invoked when the popover opens. */ onOpen?: () => void; /** * A callback function invoked when the menu is scrolled. */ onScroll?: React.UIEventHandler; /** * A callback function for loading additional list items. * Called when the list is scrolled to the bottom or all items in the list are visible. * This is called with an event argument if this is the result of a scroll. * * This should be set this to `null` when all items are loaded. */ onScrollBottom?: MultiselectScrollBottomHandler; /** * If 'value' is undefined or doesn't match an item, the Button will display this text. */ placeholder?: string; /** Prepend removes rounded borders from the left side. */ prepend?: boolean; /** * See `repositionMode` on `Popover` for details. */ repositionMode?: 'none' | 'flip'; /** * Determines how to display Select all/Clear all. * Only supported when `compact=true`. * * By default, selection applies only to currently loaded options. * Use `onChange` for custom selection behavior. * * @deprecatedValue 'buttongroup' * The 'buttongroup' value is deprecated and will be removed in a future major version. */ selectAllAppearance?: 'buttongroup' | 'checkbox' | 'none'; /** * When `compact=true`, move selected values to the top of the list on next open (default), immediately, or not at all. */ showSelectedValuesFirst?: 'nextOpen' | 'immediately' | 'never'; /** Pressing Tab while entering an input confirms the new value. Requires `allowNewValues`. */ tabConfirmsNewValue?: boolean; /** * Value will be matched to one of the children to deduce the label and/or icon for the * toggle. */ values?: (string | number | boolean)[]; /** * @private Experimental. Use a virtualized `ResultsMenu` variant which will only render at most * `virtualization * 3` options in the DOM at any given time, and will have a type of infinite scroll behavior. * This feature is only available in the `compact` variant * @throws if `virtualization` is defined but less than 2 */ virtualization?: number; } interface MultiselectPropsBaseControlled extends MultiselectPropsBase { defaultValues?: never; onChange: MultiselectChangeHandler; values?: (string | number | boolean)[]; } interface MultiselectPropsBaseUncontrolled extends MultiselectPropsBase { defaultValues?: (string | number | boolean)[]; values?: never; } interface MultiselectPropsBaseNormal extends MultiselectPropsBase { compact?: false; elementRef?: React.Ref; showSelectedValuesFirst?: never; } interface MultiselectPropsBaseCompact extends MultiselectPropsBase { compact: true; elementRef?: React.Ref; showSelectedValuesFirst?: 'nextOpen' | 'immediately' | 'never'; /** @private */ toggle?: CompactPropsBase['toggle']; } type MultiselectNormalProps = ComponentProps<(MultiselectPropsBaseControlled | MultiselectPropsBaseUncontrolled) & MultiselectPropsBaseNormal, 'div'>; type MultiselectCompactProps = ComponentProps<(MultiselectPropsBaseControlled | MultiselectPropsBaseUncontrolled) & MultiselectPropsBaseCompact, 'button'>; type MultiselectProps = MultiselectNormalProps | MultiselectCompactProps; declare function Multiselect({ allowNewValues, animateLoading, append, compact, children, controlledFilter, defaultPlacement, defaultValues, describedBy, disabled, elementRef, error, filter, footerMessage, inline, inputId, inputRef, isLoadingOptions, labelledBy, loadingMessage, menuStyle, name, noOptionsMessage, onChange, onClose, onFilterChange, onOpen, onScroll, onScrollBottom, placeholder, prepend, repositionMode, selectAllAppearance, showSelectedValuesFirst, tabConfirmsNewValue, values, virtualization, ...otherProps }: MultiselectProps): React.JSX.Element; declare namespace Multiselect { var componentType: string; var Option: typeof import("./Option").default; var Heading: typeof import("@splunk/react-ui/Menu").Heading; var Divider: typeof import("@splunk/react-ui/Menu").Divider; var propTypes: { allowNewValues: PropTypes.Requireable; animateLoading: PropTypes.Requireable; append: PropTypes.Requireable; children: PropTypes.Requireable; compact: PropTypes.Requireable; controlledFilter: PropTypes.Requireable; defaultPlacement: PropTypes.Requireable; defaultValues: PropTypes.Requireable; describedBy: PropTypes.Requireable; disabled: PropTypes.Requireable>; elementRef: PropTypes.Requireable; error: PropTypes.Requireable; filter: PropTypes.Requireable; footerMessage: PropTypes.Requireable; inline: PropTypes.Requireable; inputId: PropTypes.Requireable; inputRef: PropTypes.Requireable; isLoadingOptions: PropTypes.Requireable; labelledBy: PropTypes.Requireable; loadingMessage: PropTypes.Requireable; /** @private. */ maxLabelItems: PropTypes.Requireable; menuStyle: PropTypes.Requireable; name: PropTypes.Requireable; noOptionsMessage: PropTypes.Requireable; onChange: PropTypes.Requireable<(...args: any[]) => any>; onClose: PropTypes.Requireable<(...args: any[]) => any>; onFilterChange: PropTypes.Requireable<(...args: any[]) => any>; onOpen: PropTypes.Requireable<(...args: any[]) => any>; onScroll: PropTypes.Requireable<(...args: any[]) => any>; onScrollBottom: PropTypes.Requireable<(...args: any[]) => any>; placeholder: PropTypes.Requireable; prepend: PropTypes.Requireable; repositionMode: PropTypes.Requireable; selectAllAppearance: PropTypes.Requireable; showSelectedValuesFirst: PropTypes.Requireable; tabConfirmsNewValue: PropTypes.Requireable; values: PropTypes.Requireable; /** @private */ virtualization: PropTypes.Requireable; }; } export default Multiselect; export { Divider, Heading, MultiselectChangeHandler, MultiselectFilterChangeHandler, MultiselectScrollBottomHandler, Option, }; export type { MultiselectPropsBase, MultiselectProps };