@carbon/ibm-products
Version:
Carbon for IBM Products
217 lines (205 loc) • 7.57 kB
JavaScript
/**
* Copyright IBM Corp. 2020, 2025
*
* This source code is licensed under the Apache-2.0 license found in the
* LICENSE file in the root directory of this source tree.
*/
'use strict';
var _rollupPluginBabelHelpers = require('../../_virtual/_rollupPluginBabelHelpers.js');
var react = require('@carbon/react');
var React = require('react');
var index = require('../../_virtual/index.js');
var cx = require('classnames');
var devtools = require('../../global/js/utils/devtools.js');
var settings = require('../../settings.js');
// The block part of our conventional BEM class names (blockClass__E--M).
const blockClass = `${settings.pkg.prefix}--search-bar`;
const componentName = 'SearchBar';
// NOTE: the component SCSS is not imported here: it is rolled up separately.
// Default values for props
const defaults = {
onSubmit: () => {},
onChange: () => {},
hideScopesLabel: true
};
exports.SearchBar = /*#__PURE__*/React.forwardRef((_ref, ref) => {
let {
// The component props, in alphabetical order (for consistency).
className,
clearButtonLabelText,
hideScopesLabel = defaults.hideScopesLabel,
labelText,
onChange = defaults.onChange,
onSubmit = defaults.onSubmit,
placeholderText,
scopes = [],
scopesTypeLabel,
scopeToString,
selectedScopes = [],
sortItems,
submitLabel,
translateWithId,
value,
// Collect any other property values passed in.
...rest
} = _ref;
const [text, setText] = React.useState(value || '');
const [_selectedScopes, setSelectedScopes] = React.useState(selectedScopes || []);
const [isInputDirty, setIsInputDirty] = React.useState(false);
React.useEffect(() => {
if (!text || !text.length) {
setIsInputDirty(false);
} else {
setIsInputDirty(true);
}
}, [text]);
/**
* Handler for form submit that calls onSubmit prop.
* @param {Event} event Submit event generated.
*/
const handleSubmit = event => {
event.preventDefault();
const eventObject = {
value: text
};
if (scopes.length > 0) {
eventObject.selectedScopes = _selectedScopes;
}
onSubmit(eventObject);
};
/**
* Handler for when scope selection changes that calls onChangeProp.
* @param {{selectedItems: Array<any>}} {selectedItems} Object containing array of selected items.
*/
const handleSearchScopeChange = _ref2 => {
let {
selectedItems
} = _ref2;
setSelectedScopes(selectedItems);
onChange({
selectedScopes: selectedItems,
value: text
});
};
/**
* Handler for search input changes that calls onChange prop.
* @param {KeyboardEvent} event Event object from input change.
*/
const handleInputChange = event => {
const {
value
} = event.target;
const eventObject = {
value
};
if (scopes.length > 0) {
eventObject.selectedScopes = selectedScopes;
}
setText(value);
onChange(eventObject);
};
const multiSelectProps = {
initialSelectedItems: selectedScopes,
items: scopes,
itemToString: scopeToString,
label: scopesTypeLabel,
sortItems,
translateWithId
};
return /*#__PURE__*/React.createElement("form", _rollupPluginBabelHelpers.extends({}, rest, {
ref: ref
}, devtools.getDevtoolsProps(componentName), {
className: cx(blockClass, className, {
[`${blockClass}--hide-scopes-label`]: hideScopesLabel
}),
onSubmit: handleSubmit
}), scopes?.length ? /*#__PURE__*/React.createElement(react.MultiSelect, _rollupPluginBabelHelpers.extends({}, multiSelectProps, {
id: `${blockClass}__multi-select`,
className: `${blockClass}__scopes`,
onChange: handleSearchScopeChange,
size: "lg"
})) : null, /*#__PURE__*/React.createElement(react.Search, {
className: `${blockClass}__input`,
closeButtonLabelText: clearButtonLabelText,
labelText: labelText,
name: 'search-input',
onChange: handleInputChange,
placeholder: placeholderText,
value: text,
size: "lg"
}), /*#__PURE__*/React.createElement(react.Button, {
name: "search-submit",
kind: "primary",
type: "submit",
className: `${blockClass}__submit`,
disabled: !isInputDirty
}, submitLabel));
});
// Return a placeholder if not released and not enabled by feature flag
exports.SearchBar = settings.pkg.checkComponentEnabled(exports.SearchBar, componentName);
// The display name of the component, used by React. Note that displayName
// is used in preference to relying on function.name.
exports.SearchBar.displayName = componentName;
const conditionalScopePropValidator = function (props, propName, componentName) {
if (props.scopes && props.scopes.length > 0 && !props[propName]) {
return new Error(`Required \`${propName}\` when \`scopes\` prop type is supplied to \`${componentName}\`. Validation failed.`);
}
/**@ts-ignore */
for (var _len = arguments.length, rest = new Array(_len > 3 ? _len - 3 : 0), _key = 3; _key < _len; _key++) {
rest[_key - 3] = arguments[_key];
}
return index.default.string(props, propName, componentName, ...rest);
};
const deprecatedProps = {
/**
* **Deprecated**
*
* Provide accessible label text for the scopes MultiSelect.
*/
titleText: index.default.string
};
// The types and DocGen commentary for the component props,
// in alphabetical order (for consistency).
// See https://www.npmjs.com/package/prop-types#usage.
exports.SearchBar.propTypes = {
/** @type {string} Optional additional class name. */
className: index.default.string,
/** @type {string} The label text for the search text input. */
clearButtonLabelText: index.default.string.isRequired,
/**
* Whether or not the scopes MultiSelect label is visually hidden.
*/
hideScopesLabel: index.default.bool,
/** @type {string} The label text for the search text input. */
labelText: index.default.string.isRequired,
/** @type {Function} Function handler for when the user changes their query search. */
onChange: index.default.func,
/** @type {Function} Function handler for when the user submits a search. */
onSubmit: index.default.func,
/** @type {string} Placeholder text to be displayed in the search input. */
placeholderText: index.default.string.isRequired,
/** @type {Function} Function to get the text for each scope to display in dropdown. */
scopeToString: index.default.func,
/** @type {Array<any>} Array of allowed search scopes. */
/**@ts-ignore */
scopes: index.default.arrayOf(index.default.oneOfType([index.default.string, index.default.object])),
/** @type {string} The name text for the search scope type. */
scopesTypeLabel: conditionalScopePropValidator,
/** @type {Array<any> Array of initially selected search scopes. */
/**@ts-ignore */
selectedScopes: index.default.arrayOf(index.default.oneOfType([index.default.string, index.default.object])),
/**
* Optional custom sorting algorithm for an array of scope items.
* By default, scope items are sorted in ascending alphabetical order,
* with "selected" items moved to the start of the scope items array.
*/
sortItems: index.default.func,
/** @type {string} The label text for the search submit button. */
submitLabel: index.default.string.isRequired,
/** @type {func} Callback function for translating MultiSelect's child ListBoxMenuIcon SVG title. */
translateWithId: index.default.func,
/** @type {string} Search query value. */
value: index.default.string,
...deprecatedProps
};
exports.deprecatedProps = deprecatedProps;