@breakaway/react-core
Version:
This library provides a set of common React components for use with the PatternFly reference implementation.
171 lines • 12.3 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.SearchInput = void 0;
const tslib_1 = require("tslib");
const React = tslib_1.__importStar(require("react"));
const react_styles_1 = require("@breakaway/react-styles");
const Button_1 = require("../Button");
const Badge_1 = require("../Badge");
const angle_down_icon_1 = tslib_1.__importDefault(require('@patternfly/react-icons/dist/js/icons/angle-down-icon'));
const angle_up_icon_1 = tslib_1.__importDefault(require('@patternfly/react-icons/dist/js/icons/angle-up-icon'));
const times_icon_1 = tslib_1.__importDefault(require('@patternfly/react-icons/dist/js/icons/times-icon'));
const search_icon_1 = tslib_1.__importDefault(require('@patternfly/react-icons/dist/js/icons/search-icon'));
const caret_down_icon_1 = tslib_1.__importDefault(require('@patternfly/react-icons/dist/js/icons/caret-down-icon'));
const arrow_right_icon_1 = tslib_1.__importDefault(require('@patternfly/react-icons/dist/js/icons/arrow-right-icon'));
const AdvancedSearchMenu_1 = require("./AdvancedSearchMenu");
const TextInputGroup_1 = require("../TextInputGroup");
const InputGroup_1 = require("../InputGroup");
const helpers_1 = require("../../helpers");
const SearchInputBase = (_a) => {
var { className, value = '', attributes = [], formAdditionalItems, hasWordsAttrLabel = 'Has words', advancedSearchDelimiter, placeholder, hint, onChange, onSearch, onClear, onToggleAdvancedSearch, isAdvancedSearchOpen, resultsCount, onNextClick, onPreviousClick, innerRef, expandableInput, 'aria-label': ariaLabel = 'Search input', resetButtonLabel = 'Reset', openMenuButtonAriaLabel = 'Open advanced search', previousNavigationButtonAriaLabel = 'Previous', isPreviousNavigationButtonDisabled = false, isNextNavigationButtonDisabled = false, nextNavigationButtonAriaLabel = 'Next', submitSearchButtonLabel = 'Search', isDisabled = false, appendTo, removeFindDomNode = false, type = 'text' } = _a, props = tslib_1.__rest(_a, ["className", "value", "attributes", "formAdditionalItems", "hasWordsAttrLabel", "advancedSearchDelimiter", "placeholder", "hint", "onChange", "onSearch", "onClear", "onToggleAdvancedSearch", "isAdvancedSearchOpen", "resultsCount", "onNextClick", "onPreviousClick", "innerRef", "expandableInput", 'aria-label', "resetButtonLabel", "openMenuButtonAriaLabel", "previousNavigationButtonAriaLabel", "isPreviousNavigationButtonDisabled", "isNextNavigationButtonDisabled", "nextNavigationButtonAriaLabel", "submitSearchButtonLabel", "isDisabled", "appendTo", "removeFindDomNode", "type"]);
const [isSearchMenuOpen, setIsSearchMenuOpen] = React.useState(false);
const [searchValue, setSearchValue] = React.useState(value);
const searchInputRef = React.useRef(null);
const ref = React.useRef(null);
const searchInputInputRef = innerRef || ref;
const searchInputExpandableToggleRef = React.useRef(null);
const [focusAfterExpandChange, setFocusAfterExpandChange] = React.useState(false);
const { isExpanded, onToggleExpand, toggleAriaLabel } = expandableInput || {};
React.useEffect(() => {
var _a, _b;
// this effect and the focusAfterExpandChange variable are needed to focus the input/toggle as needed when the
// expansion toggle is fired without focusing on mount
if (!focusAfterExpandChange) {
return;
}
else if (isExpanded) {
(_a = searchInputInputRef === null || searchInputInputRef === void 0 ? void 0 : searchInputInputRef.current) === null || _a === void 0 ? void 0 : _a.focus();
}
else {
(_b = searchInputExpandableToggleRef === null || searchInputExpandableToggleRef === void 0 ? void 0 : searchInputExpandableToggleRef.current) === null || _b === void 0 ? void 0 : _b.focus();
}
setFocusAfterExpandChange(false);
}, [focusAfterExpandChange, isExpanded, searchInputInputRef, searchInputExpandableToggleRef]);
React.useEffect(() => {
setSearchValue(value);
}, [value]);
React.useEffect(() => {
if (attributes.length > 0 && !advancedSearchDelimiter) {
// eslint-disable-next-line no-console
console.error('An advancedSearchDelimiter prop is required when advanced search attributes are provided using the attributes prop');
}
});
React.useEffect(() => {
setIsSearchMenuOpen(isAdvancedSearchOpen);
}, [isAdvancedSearchOpen]);
const onChangeHandler = (value, event) => {
if (onChange) {
onChange(value, event);
}
setSearchValue(value);
};
const onToggle = (e) => {
const isOpen = !isSearchMenuOpen;
setIsSearchMenuOpen(isOpen);
if (onToggleAdvancedSearch) {
onToggleAdvancedSearch(e, isOpen);
}
};
const onSearchHandler = (event) => {
event.preventDefault();
if (onSearch) {
onSearch(value, event, getAttrValueMap());
}
setIsSearchMenuOpen(false);
};
const getAttrValueMap = () => {
const attrValue = {};
const pairs = searchValue.split(' ');
pairs.map(pair => {
const splitPair = pair.split(advancedSearchDelimiter);
if (splitPair.length === 2) {
attrValue[splitPair[0]] = splitPair[1];
}
else if (splitPair.length === 1) {
attrValue.haswords = attrValue.hasOwnProperty('haswords')
? `${attrValue.haswords} ${splitPair[0]}`
: splitPair[0];
}
});
return attrValue;
};
const onEnter = (event) => {
if (event.key === 'Enter') {
onSearchHandler(event);
}
};
const onClearInput = (e) => {
if (onClear) {
onClear(e);
}
if (searchInputInputRef && searchInputInputRef.current) {
searchInputInputRef.current.focus();
}
};
const onExpandHandler = (event) => {
setSearchValue('');
onToggleExpand(isExpanded, event);
setFocusAfterExpandChange(true);
};
const renderUtilities = value && (resultsCount || (!!onNextClick && !!onPreviousClick) || (!!onClear && !expandableInput));
const buildTextInputGroup = (_a = {}) => {
var searchInputProps = tslib_1.__rest(_a, []);
return (React.createElement(TextInputGroup_1.TextInputGroup, Object.assign({ isDisabled: isDisabled }, searchInputProps),
React.createElement(TextInputGroup_1.TextInputGroupMain, { hint: hint, icon: React.createElement(search_icon_1.default, null), innerRef: searchInputInputRef, value: searchValue, placeholder: placeholder, "aria-label": ariaLabel, onKeyDown: onEnter, onChange: onChangeHandler, type: type }),
renderUtilities && (React.createElement(TextInputGroup_1.TextInputGroupUtilities, null,
resultsCount && React.createElement(Badge_1.Badge, { isRead: true }, resultsCount),
!!onNextClick && !!onPreviousClick && (React.createElement("div", { className: "pf-c-text-input-group__group" },
React.createElement(Button_1.Button, { variant: Button_1.ButtonVariant.plain, "aria-label": previousNavigationButtonAriaLabel, isDisabled: isDisabled || isPreviousNavigationButtonDisabled, onClick: onPreviousClick },
React.createElement(angle_up_icon_1.default, null)),
React.createElement(Button_1.Button, { variant: Button_1.ButtonVariant.plain, "aria-label": nextNavigationButtonAriaLabel, isDisabled: isDisabled || isNextNavigationButtonDisabled, onClick: onNextClick },
React.createElement(angle_down_icon_1.default, null)))),
!!onClear && !expandableInput && (React.createElement(Button_1.Button, { variant: Button_1.ButtonVariant.plain, isDisabled: isDisabled, "aria-label": resetButtonLabel, onClick: onClearInput },
React.createElement(times_icon_1.default, null)))))));
};
const expandableToggle = (React.createElement(Button_1.Button, { variant: Button_1.ButtonVariant.plain, "aria-label": toggleAriaLabel, "aria-expanded": isExpanded, icon: isExpanded ? React.createElement(times_icon_1.default, null) : React.createElement(search_icon_1.default, null), onClick: onExpandHandler, ref: searchInputExpandableToggleRef }));
const buildExpandableSearchInput = (_a = {}) => {
var searchInputProps = tslib_1.__rest(_a, []);
return (React.createElement(InputGroup_1.InputGroup, Object.assign({}, searchInputProps),
buildTextInputGroup(),
expandableToggle));
};
const buildSearchTextInputGroup = (_a = {}) => {
var searchInputProps = tslib_1.__rest(_a, []);
if (expandableInput) {
return buildExpandableSearchInput(Object.assign({}, searchInputProps));
}
return buildTextInputGroup(Object.assign({}, searchInputProps));
};
const buildSearchTextInputGroupWithExtraButtons = (_a = {}) => {
var searchInputProps = tslib_1.__rest(_a, []);
return (React.createElement(InputGroup_1.InputGroup, Object.assign({}, searchInputProps),
buildTextInputGroup(),
(attributes.length > 0 || onToggleAdvancedSearch) && (React.createElement(Button_1.Button, { className: isSearchMenuOpen && 'pf-m-expanded', variant: Button_1.ButtonVariant.control, "aria-label": openMenuButtonAriaLabel, onClick: onToggle, isDisabled: isDisabled, "aria-expanded": isSearchMenuOpen },
React.createElement(caret_down_icon_1.default, null))),
!!onSearch && (React.createElement(Button_1.Button, { type: "submit", variant: Button_1.ButtonVariant.control, "aria-label": submitSearchButtonLabel, onClick: onSearchHandler, isDisabled: isDisabled || !searchValue },
React.createElement(arrow_right_icon_1.default, null))),
expandableInput && expandableToggle));
};
const searchInputProps = Object.assign(Object.assign({}, props), { className: className && react_styles_1.css(className), innerRef: searchInputRef });
if (!!expandableInput && !isExpanded) {
return React.createElement(InputGroup_1.InputGroup, Object.assign({}, searchInputProps), expandableToggle);
}
if (!!onSearch || attributes.length > 0 || !!onToggleAdvancedSearch) {
if (attributes.length > 0) {
const AdvancedSearch = (React.createElement("div", null,
React.createElement(AdvancedSearchMenu_1.AdvancedSearchMenu, { value: value, parentRef: searchInputRef, parentInputRef: searchInputInputRef, onSearch: onSearch, onClear: onClear, onChange: onChange, onToggleAdvancedMenu: onToggle, resetButtonLabel: resetButtonLabel, submitSearchButtonLabel: submitSearchButtonLabel, attributes: attributes, formAdditionalItems: formAdditionalItems, hasWordsAttrLabel: hasWordsAttrLabel, advancedSearchDelimiter: advancedSearchDelimiter, getAttrValueMap: getAttrValueMap, isSearchMenuOpen: isSearchMenuOpen })));
const AdvancedSearchWithPopper = (React.createElement("div", Object.assign({ className: react_styles_1.css(className), ref: searchInputRef }, props),
React.createElement(helpers_1.Popper, { trigger: buildSearchTextInputGroupWithExtraButtons(), popper: AdvancedSearch, isVisible: isSearchMenuOpen, enableFlip: true, appendTo: () => appendTo || searchInputRef.current, removeFindDomNode: removeFindDomNode })));
const AdvancedSearchInline = (React.createElement("div", Object.assign({ className: react_styles_1.css(className), ref: searchInputRef }, props),
buildSearchTextInputGroupWithExtraButtons(),
AdvancedSearch));
return appendTo !== 'inline' ? AdvancedSearchWithPopper : AdvancedSearchInline;
}
return buildSearchTextInputGroupWithExtraButtons(Object.assign({}, searchInputProps));
}
return buildSearchTextInputGroup(searchInputProps);
};
SearchInputBase.displayName = 'SearchInputBase';
exports.SearchInput = React.forwardRef((props, ref) => (React.createElement(SearchInputBase, Object.assign({}, props, { innerRef: ref }))));
exports.SearchInput.displayName = 'SearchInput';
//# sourceMappingURL=SearchInput.js.map