import React from 'react'; import PropTypes from 'prop-types'; import { Divider, Heading } from '@splunk/react-ui/Menu'; import { TextBlurHandler, TextChangeHandler, TextFocusHandler } from '@splunk/react-ui/Text'; import Option from './OptionBase'; import SelectAllOption from './SelectAllOption'; import { ComponentProps } from '../utils/types'; import type { OptionClickHandler } from './OptionBase'; type SelectBaseFilterChangeHandler = (event: React.ChangeEvent | React.FocusEvent | React.MouseEvent | React.KeyboardEvent, data: { keyword: string; }) => void; type SelectBaseChangeReason = 'valueToggle' | 'selectAll' | 'clearAll'; type SelectBaseChangeHandler = (event: React.MouseEvent | React.KeyboardEvent, data: { name?: string; values: (string | number | boolean)[]; reason: SelectBaseChangeReason; }) => void; type SelectBaseScrollBottomHandler = (event: React.UIEvent | React.KeyboardEvent | null) => void; interface SelectBasePropsBase { /** * Whether or not to allow entered keyboard printable characters to match options. * Keymatching is disabled when using filtering, multiselect, or loading. */ allowKeyMatching?: boolean; animateLoading?: boolean; /** * Change the style of the button or link. */ appearance?: 'default' | 'link' | 'subtle'; /** * Remove rounding from the left side of the toggle. */ append?: boolean; /** * Allow the user to add arbitrary values. */ allowNewValues?: boolean; /** * `children` should be `Multiselect.Option`, `Multiselect.Heading`, or * `Multiselect.Divider`. */ children?: React.ReactNode; /** * 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 values to keep the values uncontrolled. */ defaultValues?: (string | number | boolean)[]; /** * The id of the description. When placed in a ControlGroup, this 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. This can also be used to fetch new * results. */ 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. This prop's value is set as the `aria-labelledby` attribute. * ControlGroup automatically sets this prop. */ labelledBy?: string; /** * Text presented in the label for this field. * This prop's value is merged with the current value and set as the `aria-label` attribute. * If labelledBy is passed this prop is ignored. */ labelText?: 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. */ menuStyle?: React.CSSProperties; /** * Allow multiple values to be selected. */ multiple: boolean; /** 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 not loading, such as when * there are no Options matching the filter. This can be customized to the type of content, * such as "No matching dashboards"; 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?: SelectBaseChangeHandler; /** * 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?: SelectBaseScrollBottomHandler; /** * A callback with the change event and value of the filter box. Providing this callback and * setting the `filter` prop to `"controlled"` enables you to filter and update the children by other * criteria. */ onFilterChange?: SelectBaseFilterChangeHandler; /** * A callback function invoked when the popover closes. */ onClose?: () => void; /** * A callback function invoked when the popover opens. */ onOpen?: () => void; /** @private. */ required?: boolean; /** * If 'values' is undefined or don't match an item, the Button will display this text. */ placeholder?: string; /** * When used outside of a control group, it can be useful to include the label on the toggle. */ prefixLabel?: string; /** * Remove rounding from the left side of the toggle. */ prepend?: boolean; /** * See `repositionMode` on `Popover` for details. */ repositionMode?: 'none' | 'flip'; /** * Determines how to display Select all/Clear all. * * By default, selection applies only to currently loaded options. * Use `onChange` for custom selection behavior. */ selectAllAppearance?: 'buttongroup' | 'checkbox' | 'none'; showSelectedValuesFirst?: 'nextOpen' | 'immediately' | 'never'; /** * Places this string after the selected label. */ suffixLabel?: string; /** Pressing tab while entering an input confirms the new value. Requires `allowNewValues`. */ tabConfirmsNewValue?: boolean; /** * Values 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. * @throws if `virtualization` is defined but less than 2 */ virtualization?: number; /** * @private * * A toggle, such as a button or equivalent component that accepts `ref`, must be passed. * This prop is only supported for Select and Multiselect Compact. * `aria-haspopup`, `aria-expanded`, and `aria-controls` attributes are applied to the toggle to support accessibility. * The result of the `ref` placed on the toggle must be an instance of `HTMLElement`. Results that are instances * of class components are not supported. `Button`, `Clickable`, and `Link` are exempt from this restriction. * Also see ["Forwarding Refs"](https://reactjs.org/docs/forwarding-refs.html). */ toggle?: React.ReactElement; /** * Controls whether the `children` or `label` of the selected `Option` is rendered on the toggle button. */ toggleContent?: 'optionChildren' | 'optionLabel'; } interface SelectBasePropsBaseControlled extends SelectBasePropsBase { defaultValues?: never; onChange: SelectBaseChangeHandler; values?: (string | number | boolean)[]; } interface SelectBasePropsBaseUncontrolled extends SelectBasePropsBase { defaultValues?: (string | number | boolean)[]; values?: never; } type SelectBaseProps = ComponentProps; type OptionElement = React.ReactElement, typeof Option>; type ChildrenElement = React.ReactElement, typeof Divider | typeof Heading> | OptionElement; declare function isOption(child: ChildrenElement): child is OptionElement; interface ControlsProps extends Pick { activeItemId: string; filterA11yId?: string; filterKeyword: string; hasChildren: boolean; menuListboxId: string; onClearAll: React.MouseEventHandler; onSelectAll: React.MouseEventHandler; onTextBlur: TextBlurHandler; onTextChange: TextChangeHandler; onTextFocus: TextFocusHandler; onTextKeyDown: React.KeyboardEventHandler; optionSelection: React.MutableRefObject<'all' | 'some' | 'none'>; placement: 'above' | 'below' | 'left' | 'right' | 'misaligned' | null; textHasFocus: boolean; } declare const Controls: ({ activeItemId, filterA11yId, filterKeyword, hasChildren, inputId, inputRef, menuListboxId, multiple, onClearAll, onSelectAll, onTextBlur, onTextChange, onTextFocus, onTextKeyDown, optionSelection, placement, selectAllAppearance, textHasFocus, }: ControlsProps) => React.JSX.Element; declare function SelectBase({ allowKeyMatching, animateLoading, appearance, append, allowNewValues, children, defaultPlacement, defaultValues, describedBy, disabled, elementRef, error, filter, footerMessage, inline, inputId, inputRef, isLoadingOptions, labelledBy, labelText, loadingMessage, menuStyle, multiple, name, noOptionsMessage, onChange, onScroll, onScrollBottom, onFilterChange, onClick, onClose, onOpen, required, placeholder, prefixLabel, prepend, repositionMode, selectAllAppearance, showSelectedValuesFirst, suffixLabel, tabConfirmsNewValue, values, virtualization, toggle, toggleContent, maxLabelItems, ...otherProps }: SelectBaseProps): React.JSX.Element; declare namespace SelectBase { var propTypes: { allowKeyMatching: PropTypes.Requireable; allowNewValues: PropTypes.Requireable; animateLoading: PropTypes.Requireable; appearance: PropTypes.Requireable; append: PropTypes.Requireable; children: 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; labelText: PropTypes.Requireable; loadingMessage: PropTypes.Requireable; /** @private. */ maxLabelItems: PropTypes.Requireable; menuStyle: PropTypes.Requireable; multiple: PropTypes.Requireable; name: PropTypes.Requireable; noOptionsMessage: PropTypes.Requireable; onChange: PropTypes.Requireable<(...args: any[]) => any>; onClick: 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>; /** @private. */ required: PropTypes.Requireable; placeholder: PropTypes.Requireable; prefixLabel: PropTypes.Requireable; prepend: PropTypes.Requireable; repositionMode: PropTypes.Requireable; selectAllAppearance: PropTypes.Requireable; showSelectedValuesFirst: PropTypes.Requireable; suffixLabel: PropTypes.Requireable; tabConfirmsNewValue: PropTypes.Requireable; toggle: PropTypes.Requireable; toggleContent: PropTypes.Requireable; values: PropTypes.Requireable; /** @private. */ virtualization: PropTypes.Requireable; }; var componentType: string; var Option: typeof import("./OptionBase").default; var Divider: typeof import("@splunk/react-ui/Menu").Divider; var Heading: typeof import("@splunk/react-ui/Menu").Heading; } export default SelectBase; export { Controls, ChildrenElement, Divider, Heading, Option, SelectAllOption, OptionClickHandler, SelectBaseChangeHandler, SelectBaseChangeReason, SelectBaseFilterChangeHandler, SelectBaseProps, isOption, };