@geneui/components
Version:
The Gene UI components library designed for BI tools
893 lines (878 loc) • 36.8 kB
JavaScript
import { _ as _extends } from '../_rollupPluginBabelHelpers-e8fb2e5c.js';
import React__default, { useRef, useState, useCallback, useEffect, useMemo } from 'react';
import PropTypes from 'prop-types';
import { c as classnames } from '../index-031ff73c.js';
import { a as dayjs } from '../dateValidation-67caec66.js';
import { h as advancedSearchConfig } from '../configs-00612ce0.js';
import useDebounce from '../hooks/useDebounce.js';
import { n as noop } from '../index-a0e4e333.js';
import useKeyDown from '../hooks/useKeyDown.js';
import useClickOutside from '../hooks/useClickOutside.js';
import { P as PopoverV2 } from '../index-08898b29.js';
import ExtendedInput from '../ExtendedInput/index.js';
import CustomScrollbar from '../Scrollbar/index.js';
import LinkButton from '../LinkButton/index.js';
import { u as useEllipsisDetection } from '../useEllipsisDetection-4d997d5d.js';
import Icon from '../Icon/index.js';
import Checkbox from '../Checkbox/index.js';
import { T as Tooltip } from '../index-6d7e99cd.js';
import SkeletonLoader from '../SkeletonLoader/index.js';
import Badge from '../Badge/index.js';
import Empty from '../Empty/index.js';
import 'react-dom';
import Button from '../Button/index.js';
import { s as styleInject } from '../style-inject.es-746bb8ed.js';
import '../_commonjsHelpers-24198af3.js';
import '../index-122432cd.js';
import '../hooks/useDeviceType.js';
import '../hooks/useWindowSize.js';
import '../GeneUIProvider/index.js';
import '../debounce-4419bc2f.js';
import '../SuggestionList/index.js';
import '../config-1053d64d.js';
import '../callAfterDelay-7272faca.js';
import '../tslib.es6-f211516f.js';
import '../checkboxRadioSwitcher-5b69d7bd.js';
import '../guid-8ddf77b3.js';
function ListElementWithCheckbox(_ref) {
let {
item,
onSelect
} = _ref;
const {
checked,
icon,
name
} = item;
const checkboxRef = useRef(null);
const [isFocused, setIsFocused] = useState(false);
const nameRef = useRef(null);
const isNameTruncated = useEllipsisDetection(nameRef);
// Handle blur event to clear focus state
const handleBlur = useCallback(() => setIsFocused(false), []);
// Handle Focus event to add focus state
const handleFocus = useCallback(() => setIsFocused(true), []);
return /*#__PURE__*/React__default.createElement("li", {
className: classnames('listElementWithCheckbox', {
'listElementWithCheckbox-hover': isFocused
})
}, /*#__PURE__*/React__default.createElement("label", {
className: "listElementWithCheckbox__label"
}, item.hasOwnProperty('checked') && /*#__PURE__*/React__default.createElement(Checkbox, {
ref: checkboxRef,
checked: checked,
onChange: () => {
onSelect(item);
},
className: "listElementWithCheckbox__checkbox",
onBlur: handleBlur,
onFocus: handleFocus
}), icon && /*#__PURE__*/React__default.createElement(Icon, {
type: icon,
className: "listElementWithCheckbox__icon"
}), name && /*#__PURE__*/React__default.createElement(Tooltip, {
text: name,
isVisible: isNameTruncated
}, /*#__PURE__*/React__default.createElement("span", {
className: "listElementWithCheckbox__name ellipsis-text",
ref: nameRef
}, name))));
}
ListElementWithCheckbox.defaultProps = {
onSelect: noop,
item: {
checked: false
}
};
ListElementWithCheckbox.propTypes = {
item: PropTypes.shape({
name: PropTypes.string,
value: PropTypes.string,
checked: PropTypes.bool,
icon: PropTypes.string
})
};
function SkeletonSet(_ref) {
let {
count,
searchResult
} = _ref;
return searchResult ? /*#__PURE__*/React__default.createElement("ul", {
className: "skeleton"
}, Array(count || 1).fill('').map((_, i) => /*#__PURE__*/React__default.createElement("li", {
className: "skeleton__searchElement",
key: i
}, /*#__PURE__*/React__default.createElement(SkeletonLoader, {
duration: +"".concat(2, ".0", i),
width: "100%",
isBusy: true
})))) : /*#__PURE__*/React__default.createElement("ul", null, Array(count || 1).fill('').map((_, i) => /*#__PURE__*/React__default.createElement("li", {
className: "skeleton__filter",
key: i
}, /*#__PURE__*/React__default.createElement(SkeletonLoader, {
duration: 2,
height: "23px",
width: "23px",
isBusy: true
}), /*#__PURE__*/React__default.createElement("span", {
style: {
width: '10px'
}
}), /*#__PURE__*/React__default.createElement(SkeletonLoader, {
duration: +"".concat(2, ".0", i),
height: "23px",
width: "".concat(Math.floor(Math.random() * 51) + 50, "%"),
isBusy: true
}))));
}
SkeletonSet.defaultProps = {};
SkeletonSet.propTypes = {};
function FilterList(_ref) {
let {
data,
skeletonCount,
onSelect
} = _ref;
const {
data: filterData,
isLoading,
onShowMoreClick,
sectionNameText,
hasActiveShowMore,
showMoreText
} = data;
const listRef = useRef(null);
const scrollbarRef = useRef(null);
const [ableToScroll, setAbleToScroll] = useState(false);
const [dataLengthSnapshots, setDataLengthSnapshots] = useState([]);
const [elementTopToScroll, setElementTopToScroll] = useState(0);
const onShowMoreHandler = useCallback(e => {
onShowMoreClick(e);
setAbleToScroll(true);
}, []);
useEffect(() => {
setDataLengthSnapshots(prev => [...prev, filterData === null || filterData === void 0 ? void 0 : filterData.length]);
}, [filterData === null || filterData === void 0 ? void 0 : filterData.length]);
useEffect(() => {
var _listRef$current, _listRef$current$chil;
const scrollToElementTop = +(listRef === null || listRef === void 0 ? void 0 : (_listRef$current = listRef.current) === null || _listRef$current === void 0 ? void 0 : (_listRef$current$chil = _listRef$current.children[dataLengthSnapshots[(dataLengthSnapshots === null || dataLengthSnapshots === void 0 ? void 0 : dataLengthSnapshots.length) - 1] - 1]) === null || _listRef$current$chil === void 0 ? void 0 : _listRef$current$chil.offsetTop);
if (!isLoading && ableToScroll) {
setElementTopToScroll(scrollToElementTop);
setAbleToScroll(false);
}
}, [isLoading]);
return /*#__PURE__*/React__default.createElement("div", {
className: "filterList__filter"
}, /*#__PURE__*/React__default.createElement(CustomScrollbar, {
autoHeightMax: 500,
className: "filterList__scrollbar",
style: {
height: '100%'
},
ref: scrollbarRef,
scrollTop: elementTopToScroll,
withSmoothScroll: true
}, /*#__PURE__*/React__default.createElement("h6", {
className: "filterList__filterHeader"
}, sectionNameText), /*#__PURE__*/React__default.createElement("ul", {
className: "filterList__filterList",
ref: listRef
}, isLoading ? /*#__PURE__*/React__default.createElement(SkeletonSet, {
count: skeletonCount
}) : filterData === null || filterData === void 0 ? void 0 : filterData.map((item, index) => /*#__PURE__*/React__default.createElement(ListElementWithCheckbox, {
key: index,
onSelect: onSelect,
item: item
})), hasActiveShowMore && /*#__PURE__*/React__default.createElement("li", {
className: "filterList__showMoreLi"
}, /*#__PURE__*/React__default.createElement(LinkButton, {
tabIndex: 0,
ariaLabel: showMoreText,
onClick: onShowMoreHandler,
className: "filterList__showMoreLink"
}, showMoreText)))));
}
FilterList.defaultProps = {
data: {
data: []
},
onSelect: noop,
skeletonCount: 5,
showMoreIsLoading: false
};
FilterList.propTypes = {
/**
* data structure for secondary filter
*/
data: PropTypes.shape({
sectionNameText: PropTypes.string,
onChange: PropTypes.func,
hasActiveShowMore: PropTypes.bool,
showMoreText: PropTypes.string,
showMoreIsLoading: PropTypes.bool,
onShowMoreClick: PropTypes.func,
isLoading: PropTypes.bool,
data: PropTypes.arrayOf(PropTypes.shape({
name: PropTypes.string,
value: PropTypes.string,
checked: PropTypes.bool,
icon: PropTypes.string,
id: PropTypes.oneOfType([PropTypes.string, PropTypes.number])
}))
}),
skeleton: PropTypes.element,
onSelect: PropTypes.func,
skeletonCount: PropTypes.number
};
function SearchResultRow(_ref) {
let {
element
} = _ref;
const {
icon,
id,
title,
name,
date,
actions
} = element;
const [isFocused, setIsFocused] = useState(false);
const [focusedIndex, setFocusedIndex] = useState(null);
const titleRef = useRef(null);
const isTitleTruncated = useEllipsisDetection(titleRef);
const nameRef = useRef(null);
const isNameTruncated = useEllipsisDetection(nameRef);
// Handle blur event to clear focus state
const handleBlur = useCallback(() => {
setFocusedIndex(null);
setIsFocused(false);
}, [element]);
// Handle Focus event to add focus state
const handleFocus = useCallback(index => {
setFocusedIndex(index);
setIsFocused(true);
}, [element]);
return /*#__PURE__*/React__default.createElement("li", {
className: classnames('searchResultRow', {
'searchResultRow-hover': isFocused
})
}, icon && /*#__PURE__*/React__default.createElement(Icon, {
type: element.icon,
className: "searchResultRow__icon"
}), /*#__PURE__*/React__default.createElement("div", {
className: "searchResultRow__info"
}, (id || title) && /*#__PURE__*/React__default.createElement("div", {
className: "searchResultRow__titleWrapper"
}, id && /*#__PURE__*/React__default.createElement("span", {
className: "searchResultRow__id"
}, id), title && /*#__PURE__*/React__default.createElement(Tooltip, {
text: title,
isVisible: isTitleTruncated
}, /*#__PURE__*/React__default.createElement("span", {
className: "searchResultRow__title ellipsis-text",
ref: titleRef
}, title))), (name || date) && /*#__PURE__*/React__default.createElement("div", {
className: "searchResultRow__nameWrapper"
}, name && /*#__PURE__*/React__default.createElement(Tooltip, {
text: name,
isVisible: isNameTruncated
}, /*#__PURE__*/React__default.createElement("span", {
className: "searchResultRow__name ellipsis-text",
ref: nameRef
}, name)), name && date && /*#__PURE__*/React__default.createElement(Icon, {
type: "bc-icon-dot",
className: "searchResultRow__dateSeparator"
}), date && /*#__PURE__*/React__default.createElement("div", {
className: "searchResultRow__dateWrapper"
}, date.labelText && /*#__PURE__*/React__default.createElement("span", {
className: "searchResultRow__dateText"
}, date.labelText), date.date && /*#__PURE__*/React__default.createElement("span", {
className: "searchResultRow__date"
}, date.date)))), /*#__PURE__*/React__default.createElement("div", {
className: classnames('searchResultRow__actions', {
'searchResultRow__actions-hover': isFocused
})
}, actions === null || actions === void 0 ? void 0 : actions.map((action, index) => /*#__PURE__*/React__default.createElement(Tooltip, {
key: index,
text: action === null || action === void 0 ? void 0 : action.description,
isVisible: !!(action !== null && action !== void 0 && action.description),
alwaysShow: !!(action !== null && action !== void 0 && action.description) && index === focusedIndex
}, /*#__PURE__*/React__default.createElement(Button, {
tabIndex: 0,
size: "medium",
icon: action.icon,
onBlur: handleBlur,
appearance: "minimal",
onFocus: () => {
handleFocus(index);
},
cornerRadius: "smooth",
onClick: () => action === null || action === void 0 ? void 0 : action.onClick(element),
className: "searchResultRow__action",
ariaLabel: action.name || action.icon
})))));
}
SearchResultRow.defaultProps = {
element: {}
};
SearchResultRow.propTypes = {
element: PropTypes.shape({
icon: PropTypes.string,
id: PropTypes.string,
title: PropTypes.string,
type: PropTypes.string,
name: PropTypes.string,
date: PropTypes.shape({
labelText: PropTypes.string,
date: PropTypes.oneOfType([PropTypes.instanceOf(dayjs), PropTypes.instanceOf(Date), PropTypes.string, PropTypes.number])
}),
actions: PropTypes.arrayOf(PropTypes.shape({
name: PropTypes.string,
icon: PropTypes.string.isRequired,
onClick: PropTypes.func,
description: PropTypes.string
}))
})
};
function SearchResult(_ref) {
let {
data,
totalCount,
noDataText,
initialData,
showMoreText,
totalCountMax,
totalCountText,
onShowMoreClick,
isSearchLoading,
showMoreIsLoading,
hasActiveShowMore,
initialDataDescription
} = _ref;
const listRef = useRef(null);
const scrollbarRef = useRef(null);
const [ableToScroll, setAbleToScroll] = useState(false);
const [dataLengthSnapshots, setDataLengthSnapshots] = useState([]);
const [elementTopToScroll, setElementTopToScroll] = useState(0);
const onShowMoreHandler = useCallback(e => {
onShowMoreClick(e);
setAbleToScroll(true);
}, []);
useEffect(() => {
setDataLengthSnapshots(prev => [...prev, data.length]);
}, [data.length]);
useEffect(() => {
var _listRef$current, _listRef$current$chil;
// Formula for getting the top of the element and adding 29px for showing showMore link and half of the last visible row.
const scrollToElementTop = +(listRef === null || listRef === void 0 ? void 0 : (_listRef$current = listRef.current) === null || _listRef$current === void 0 ? void 0 : (_listRef$current$chil = _listRef$current.children[dataLengthSnapshots[dataLengthSnapshots.length - 2] - 1]) === null || _listRef$current$chil === void 0 ? void 0 : _listRef$current$chil.offsetTop) + 29;
if (!isSearchLoading && ableToScroll) {
setElementTopToScroll(scrollToElementTop);
setAbleToScroll(false);
}
}, [isSearchLoading]);
return /*#__PURE__*/React__default.createElement("div", {
className: "searchResult"
}, isSearchLoading && /*#__PURE__*/React__default.createElement(SkeletonSet, {
searchResult: true,
count: 8
}), /*#__PURE__*/React__default.createElement(CustomScrollbar, {
autoHeightMax: 500,
className: classnames('searchResult__scrollbar', {
'searchResult__scrollbar-loading': isSearchLoading
}),
ref: scrollbarRef,
scrollTop: elementTopToScroll,
withSmoothScroll: true
}, /*#__PURE__*/React__default.createElement("div", {
className: "searchResult__header"
}, /*#__PURE__*/React__default.createElement("span", {
className: "searchResult__text"
}, totalCount > 0 && totalCountText || initialData.length > 0 && initialDataDescription), totalCount > 0 && /*#__PURE__*/React__default.createElement(Badge, {
className: "searchResult__badge",
count: totalCount,
maxCount: totalCountMax,
size: "default",
color: "primary"
})), (data === null || data === void 0 ? void 0 : data.length) > 0 || initialData.length > 0 ? /*#__PURE__*/React__default.createElement("ul", {
className: "searchResult__list",
role: "navigation",
ref: listRef
}, initialData.length > 0 ? initialData.map((elem, index) => /*#__PURE__*/React__default.createElement(SearchResultRow, {
key: index,
element: elem
})) : data === null || data === void 0 ? void 0 : data.map((elem, index) => /*#__PURE__*/React__default.createElement(SearchResultRow, {
key: index,
element: elem
})), hasActiveShowMore && /*#__PURE__*/React__default.createElement("li", {
className: "searchResult__showMoreLi"
}, /*#__PURE__*/React__default.createElement(LinkButton, {
tabIndex: 0,
ariaLabel: showMoreText,
onClick: onShowMoreHandler,
className: "searchResult__showMoreLink"
}, showMoreText))) : /*#__PURE__*/React__default.createElement(Empty, {
appearance: "without-circles",
title: noDataText,
type: "search",
className: "searchResult__empty"
})));
}
SearchResult.defaultProps = {
initialDataDescription: 'initial data description',
isSearchLoading: false,
showMoreIsLoading: false
};
SearchResult.propTypes = {
/**
* total count of data to show in badge
*/
totalCount: PropTypes.number,
/**
* text for no data to display
*/
noDataText: PropTypes.string,
/**
* If search field is empty, will show initialData for example (Recently modified data).
*/
initialData: PropTypes.arrayOf(PropTypes.shape({
icon: PropTypes.string,
id: PropTypes.string,
title: PropTypes.string,
type: PropTypes.string,
name: PropTypes.string,
date: PropTypes.shape({
labelText: PropTypes.string,
date: PropTypes.oneOfType([PropTypes.instanceOf(dayjs), PropTypes.instanceOf(Date), PropTypes.string, PropTypes.number])
}),
actions: PropTypes.arrayOf(PropTypes.shape({
name: PropTypes.string,
icon: PropTypes.string.isRequired,
onClick: PropTypes.func,
description: PropTypes.string
}))
})),
/**
* text for link under search result
*/
showMoreText: PropTypes.string,
/**
* total max count of data to show totalCountMax+ in badge
*/
totalCountMax: PropTypes.number,
/**
* label text for badge component
*/
totalCountText: PropTypes.string,
/**
* Fires an event when clicked on link under search result
*/
onShowMoreClick: PropTypes.func,
/**
* To control showMore loading state
*/
showMoreIsLoading: PropTypes.bool,
/**
* search loading state
*/
isSearchLoading: PropTypes.bool,
/**
* if hasActive hasActiveShowMore is true you will see show more link under search result
*/
hasActiveShowMore: PropTypes.bool,
/**
* If search field is empty, initialDataDescription is describing witch data is showing by default for example (Recently modified data).
*/
initialDataDescription: PropTypes.string,
/**
* data structure
* */
data: PropTypes.arrayOf(PropTypes.shape({
icon: PropTypes.string,
id: PropTypes.string,
title: PropTypes.string,
type: PropTypes.string,
name: PropTypes.string,
date: PropTypes.shape({
labelText: PropTypes.string,
date: PropTypes.oneOfType([PropTypes.instanceOf(dayjs), PropTypes.instanceOf(Date), PropTypes.string, PropTypes.number])
}),
actions: PropTypes.arrayOf(PropTypes.shape({
name: PropTypes.string,
icon: PropTypes.string.isRequired,
onClick: PropTypes.func,
description: PropTypes.string
}))
}))
};
function Content(_ref) {
let {
data,
totalCount,
noDataText,
initialData,
showMoreText,
totalCountMax,
totalCountText,
isSearchLoading,
onShowMoreClick,
hasActiveShowMore,
primaryFilterData,
secondaryFilterData,
initialDataDescription
} = _ref;
const [clonedPrimaryFilterData, setClonedPrimaryFilterData] = useState({
...primaryFilterData
});
const [clonedSecondaryFilterData, setClonedSecondaryFilterData] = useState({
...secondaryFilterData
});
useEffect(() => setClonedPrimaryFilterData({
...primaryFilterData
}), [primaryFilterData]);
useEffect(() => setClonedSecondaryFilterData({
...secondaryFilterData
}), [secondaryFilterData]);
const newFilterData = useCallback((clonedData, selectedElement) => ({
...clonedData,
data: clonedData === null || clonedData === void 0 ? void 0 : clonedData.data.map(elem => {
if (elem.id === selectedElement.id) {
elem.checked = !elem.checked;
}
return elem;
})
}), []);
const handleSelectPrimary = useCallback(selectedElement => {
const newPrimaryFilterData = newFilterData(clonedPrimaryFilterData, selectedElement);
setClonedPrimaryFilterData(newPrimaryFilterData);
primaryFilterData.onChange(newPrimaryFilterData.data);
}, [clonedPrimaryFilterData]);
const handleSelectSecondary = useCallback(selectedElement => {
const newSecondaryFilterData = newFilterData(clonedSecondaryFilterData, selectedElement);
setClonedSecondaryFilterData(newSecondaryFilterData);
secondaryFilterData.onChange(newSecondaryFilterData.data);
}, [clonedSecondaryFilterData.data]);
const skeletonCount = useMemo(() => primaryFilterData && secondaryFilterData ? 5 : 11, [primaryFilterData, secondaryFilterData]);
return /*#__PURE__*/React__default.createElement("div", {
className: "advancedSearch__content"
}, /*#__PURE__*/React__default.createElement("div", {
className: classnames('advancedSearch__searchResult', {
'advancedSearch__searchResult-border': primaryFilterData || secondaryFilterData
})
}, /*#__PURE__*/React__default.createElement(SearchResult, {
data: data,
noDataText: noDataText,
totalCount: totalCount,
initialData: initialData,
showMoreText: showMoreText,
totalCountMax: totalCountMax,
totalCountText: totalCountText,
onShowMoreClick: onShowMoreClick,
isSearchLoading: isSearchLoading,
hasActiveShowMore: hasActiveShowMore,
initialDataDescription: initialDataDescription
})), (primaryFilterData || secondaryFilterData) && /*#__PURE__*/React__default.createElement("div", {
className: "advancedSearch__filters"
}, primaryFilterData && /*#__PURE__*/React__default.createElement(FilterList, {
data: primaryFilterData,
skeletonCount: skeletonCount,
onSelect: handleSelectPrimary
}), secondaryFilterData && primaryFilterData && /*#__PURE__*/React__default.createElement("div", {
className: "advancedSearch__divider"
}), secondaryFilterData && /*#__PURE__*/React__default.createElement(FilterList, {
data: secondaryFilterData,
skeletonCount: skeletonCount,
onSelect: handleSelectSecondary
})));
}
Content.defaultProps = {};
Content.propTypes = {};
var css_248z = "[data-gene-ui-version=\"2.16.5\"] .advancedSearch{margin-left:auto;margin-right:0;min-height:3.6rem;min-width:10rem;position:relative;width:-webkit-fit-content;width:-moz-fit-content;width:fit-content}[data-gene-ui-version=\"2.16.5\"] .advancedSearch-left{margin-left:0;margin-right:auto}[data-gene-ui-version=\"2.16.5\"] .advancedSearch__wrapper{color:rgba(var(--background-sc-rgb),.75);left:auto;max-width:var(--advanced-search-width);position:absolute;right:0;top:0;width:100vw}[data-gene-ui-version=\"2.16.5\"] .advancedSearch__wrapper-left{left:0;right:auto}[data-gene-ui-version=\"2.16.5\"] .advancedSearch__popover{min-height:50rem;width:var(--advanced-search-width)}[data-gene-ui-version=\"2.16.5\"] .advancedSearch__content{color:rgba(var(--background-sc-rgb),.75);display:flex;height:52rem;justify-content:space-between;max-height:50rem!important}[data-gene-ui-version=\"2.16.5\"] .advancedSearch__searchResult{flex-grow:3;height:auto;max-height:100%}[data-gene-ui-version=\"2.16.5\"] .advancedSearch__searchResult-border{border-left:none;border-right:1px solid rgba(var(--background-sc-rgb),.3)}[data-gene-ui-version=\"2.16.5\"] [dir=rtl] .advancedSearch__searchResult-border{border-left:1px solid rgba(var(--background-sc-rgb),.3);border-right:none}[data-gene-ui-version=\"2.16.5\"] .advancedSearch__filters{width:27rem}[data-gene-ui-version=\"2.16.5\"] .advancedSearch__divider{border-bottom:1px solid rgba(var(--background-sc-rgb),.3)}[data-gene-ui-version=\"2.16.5\"] .filterList__filter{height:50%;min-height:50%;padding:.8rem 0;padding-inline-end:0;width:100%}[data-gene-ui-version=\"2.16.5\"] .filterList__filterHeader{font-size:1.2rem;padding:.8rem}[data-gene-ui-version=\"2.16.5\"] .filterList__filterList{display:flex;flex-direction:column}[data-gene-ui-version=\"2.16.5\"] .filterList__showMoreLi{margin:.8rem}[data-gene-ui-version=\"2.16.5\"] .filterList__showMoreLink{padding:.4rem .8rem}[data-gene-ui-version=\"2.16.5\"] .listElementWithCheckbox{align-items:center;display:flex;flex-wrap:nowrap;height:4rem;padding:0 1.6rem}[data-gene-ui-version=\"2.16.5\"] .listElementWithCheckbox-hover,[data-gene-ui-version=\"2.16.5\"] .listElementWithCheckbox:hover{background:rgba(var(--background-sc-rgb),.03)}[data-gene-ui-version=\"2.16.5\"] .listElementWithCheckbox__label{align-items:center;cursor:pointer;display:flex;-webkit-user-select:none;user-select:none;width:100%}[data-gene-ui-version=\"2.16.5\"] .listElementWithCheckbox__icon,[data-gene-ui-version=\"2.16.5\"] .listElementWithCheckbox__name{margin-inline-start:.8rem}[data-gene-ui-version=\"2.16.5\"] .searchResult{height:100%;padding:.8rem 0;padding-inline-end:0;position:relative}[data-gene-ui-version=\"2.16.5\"] .searchResult__scrollbar{height:100%}[data-gene-ui-version=\"2.16.5\"] .searchResult__scrollbar-loading{visibility:hidden}[data-gene-ui-version=\"2.16.5\"] .searchResult__header{align-items:center;display:flex;justify-content:flex-start;padding:.8rem;width:100%}[data-gene-ui-version=\"2.16.5\"] .searchResult__list{width:100%}[data-gene-ui-version=\"2.16.5\"] .searchResult__text{font-size:1.2rem}[data-gene-ui-version=\"2.16.5\"] .searchResult__badge{margin-inline-start:.8rem}[data-gene-ui-version=\"2.16.5\"] .searchResult__showMoreLi{margin:.8rem;padding:.8rem 0;padding-inline-start:.8rem}[data-gene-ui-version=\"2.16.5\"] .searchResult__showMoreLink{padding:.4rem}[data-gene-ui-version=\"2.16.5\"] .searchResult__empty{height:calc(100% - 5.5rem)}[data-gene-ui-version=\"2.16.5\"] .searchResultRow{align-items:center;display:flex;height:4.5rem;justify-content:space-between;margin:.4rem 0;max-width:100%;padding:.4rem .8rem;width:100%}[data-gene-ui-version=\"2.16.5\"] .searchResultRow-hover,[data-gene-ui-version=\"2.16.5\"] .searchResultRow:hover{background:rgba(var(--background-sc-rgb),.03)}[data-gene-ui-version=\"2.16.5\"] .searchResultRow__icon{padding:0 .8rem}[data-gene-ui-version=\"2.16.5\"] .searchResultRow__info{display:flex;flex-direction:column;flex-grow:2;height:100%;justify-content:space-between;overflow:hidden;padding-inline-start:.8rem;width:100%}[data-gene-ui-version=\"2.16.5\"] .searchResultRow__titleWrapper{align-items:center;display:flex;font-weight:600}[data-gene-ui-version=\"2.16.5\"] .searchResultRow__id{color:rgba(var(--background-sc-rgb),.6);margin-inline-end:.8rem}[data-gene-ui-version=\"2.16.5\"] .searchResultRow__title{color:var(--background-sc-rgb)}[data-gene-ui-version=\"2.16.5\"] .searchResultRow__nameWrapper{align-items:center;color:rgba(var(--background-sc-rgb),.6);display:flex;flex-wrap:nowrap}[data-gene-ui-version=\"2.16.5\"] .searchResultRow__name{font-size:1.2rem;white-space:nowrap}[data-gene-ui-version=\"2.16.5\"] .searchResultRow__dateSeparator{font-size:1.2rem;padding-top:.3rem}[data-gene-ui-version=\"2.16.5\"] .searchResultRow__dateWrapper{align-items:center;display:flex;font-size:1rem;padding-top:.3rem}[data-gene-ui-version=\"2.16.5\"] .searchResultRow__dateText{font-style:italic;margin-inline-end:.4rem}[data-gene-ui-version=\"2.16.5\"] .searchResultRow__actions{display:flex;height:100%}[data-gene-ui-version=\"2.16.5\"] .searchResultRow__action{color:var(--hero);cursor:pointer;margin:0 .4rem}[data-gene-ui-version=\"2.16.5\"] .skeleton{height:100%;left:0;position:absolute;top:0;width:100%}[data-gene-ui-version=\"2.16.5\"] .skeleton__filter{align-items:center;display:flex;flex-wrap:nowrap;height:4rem;padding:0 .8rem}[data-gene-ui-version=\"2.16.5\"] .skeleton__searchElement{align-items:center;display:flex;height:44px;margin:1.5rem .8rem;padding-inline-end:.8rem}";
styleInject(css_248z);
function AdvancedSearch(_ref) {
let {
data,
isOpen,
position,
onSearch,
totalCount,
noDataText,
initialData,
showMoreText,
totalCountMax,
totalCountText,
onOutsideClick,
onShowMoreClick,
isSearchLoading,
openedInputWidth,
closedInputWidth,
hasActiveShowMore,
primaryFilterData,
secondaryFilterData,
extendedInputConfigs,
initialDataDescription
} = _ref;
const parentRef = useRef(null);
const searchRef = useRef(null);
const [popoverOpen, setPopoverOpen] = useState(false);
const [initialDataState, setInitialDataState] = useState([]);
const [searchValue, setSearchValue] = useState(null);
const debouncedSearchValue = useDebounce(searchValue, 300);
const isOpenControlled = useMemo(() => isOpen !== undefined, [isOpen]);
useEffect(() => {
if (debouncedSearchValue === null) return;
onSearch(debouncedSearchValue);
}, [debouncedSearchValue]);
const openPopoverHandler = e => {
e && (e.currentTarget.onFocus = true);
if (!popoverOpen) setPopoverOpen(true);
};
const closePopoverHandler = useCallback(() => setPopoverOpen(false), []);
useKeyDown(e => {
var _searchRef$current;
switch (e.key) {
case 'Escape':
(searchRef === null || searchRef === void 0 ? void 0 : searchRef.current) && (searchRef === null || searchRef === void 0 ? void 0 : (_searchRef$current = searchRef.current) === null || _searchRef$current === void 0 ? void 0 : _searchRef$current.blur());
closePopoverHandler();
break;
}
}, [close, focus, blur, popoverOpen], parentRef, ['Escape']);
// initial data setter
useEffect(() => {
setInitialDataState((debouncedSearchValue === null || debouncedSearchValue === void 0 ? void 0 : debouncedSearchValue.length) > 0 ? [] : initialData);
}, [debouncedSearchValue]);
const inputAndPopoverWidthVariable = useMemo(() => ({
'--advanced-search-width': (isOpenControlled ? isOpen : popoverOpen) ? "".concat(openedInputWidth, "vw") : closedInputWidth
}), [popoverOpen, isOpenControlled, isOpen, openedInputWidth, closedInputWidth]);
const handleOutsideClick = useClickOutside(onOutsideClick);
return /*#__PURE__*/React__default.createElement("div", {
className: classnames('advancedSearch', {
'advancedSearch-left': position === advancedSearchConfig.positions.left
}),
ref: handleOutsideClick
}, /*#__PURE__*/React__default.createElement("div", {
className: classnames('advancedSearch__wrapper', {
'advancedSearch__wrapper-left': position === advancedSearchConfig.positions.left
}),
style: inputAndPopoverWidthVariable,
ref: parentRef
}, /*#__PURE__*/React__default.createElement(PopoverV2, {
position: "bottom",
screenType: "desktop",
isOpen: isOpenControlled ? isOpen : popoverOpen,
scrollbarNeeded: false,
extendTargetWidth: false,
className: "advancedSearch__popover",
onClickOutside: closePopoverHandler,
containerParent: parentRef === null || parentRef === void 0 ? void 0 : parentRef.current,
Content: /*#__PURE__*/React__default.createElement(Content, {
data: data,
noDataText: noDataText,
totalCount: totalCount,
showMoreText: showMoreText,
totalCountMax: totalCountMax,
initialData: initialDataState,
totalCountText: totalCountText,
onShowMoreClick: onShowMoreClick,
isSearchLoading: isSearchLoading,
primaryFilterData: primaryFilterData,
hasActiveShowMore: hasActiveShowMore,
secondaryFilterData: secondaryFilterData,
initialDataDescription: initialDataDescription
})
}, /*#__PURE__*/React__default.createElement(ExtendedInput, _extends({
canClear: true,
clickableIcon: true,
ref: searchRef,
value: searchValue,
description: false,
icon: "bc-icon-search",
flexibility: "content-size",
onChange: _ref2 => {
let {
target
} = _ref2;
return setSearchValue(target.value);
},
onClick: openPopoverHandler,
onFocus: openPopoverHandler,
placeholder: "Advanced Search",
className: "advancedSearch__extendedInput"
}, extendedInputConfigs)))), /*#__PURE__*/React__default.createElement("div", {
"data-comment": "for-popover-accessibility-to-close",
tabIndex: "0",
style: {
height: 0,
width: 0,
opacity: 0
},
onFocus: closePopoverHandler
}));
}
AdvancedSearch.propTypes = {
/**
* Position of the AdvancedSearch component.
* If set to 'right', it will stretch from right to left, and if set to 'left', it will stretch from left to right.
* By default, the component stretches from right to left.
*/
position: PropTypes.oneOf(Object.values(advancedSearchConfig.positions)),
/**
* Width of closed AdvancedSearch input.
* if you set number it will be px, or you can set string for Example 20vw
*/
closedInputWidth: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
/**
* Width of opened AdvancedSearch input.
* It can be only with a number and it will be converted to vw(viewport's width), which is equal to viewport %
*/
openedInputWidth: PropTypes.number,
/**
* See ExtendedInput components docs
*/
extendedInputConfigs: PropTypes.shape({
...ExtendedInput.propTypes
}),
/**
* data structure for primary filter
*/
primaryFilterData: PropTypes.shape({
sectionNameText: PropTypes.string,
onChange: PropTypes.func,
hasActiveShowMore: PropTypes.bool,
showMoreText: PropTypes.string,
showMoreIsLoading: PropTypes.bool,
onShowMoreClick: PropTypes.func,
isLoading: PropTypes.bool,
data: PropTypes.arrayOf(PropTypes.shape({
name: PropTypes.string,
value: PropTypes.string,
checked: PropTypes.bool,
icon: PropTypes.string,
id: PropTypes.oneOfType([PropTypes.string, PropTypes.number])
}))
}),
/**
* data structure for secondary filter
*/
secondaryFilterData: PropTypes.shape({
sectionNameText: PropTypes.string,
onChange: PropTypes.func,
hasActiveShowMore: PropTypes.bool,
showMoreText: PropTypes.string,
showMoreIsLoading: PropTypes.bool,
onShowMoreClick: PropTypes.func,
isLoading: PropTypes.bool,
data: PropTypes.arrayOf(PropTypes.shape({
name: PropTypes.string,
value: PropTypes.string,
checked: PropTypes.bool,
icon: PropTypes.string,
id: PropTypes.oneOfType([PropTypes.string, PropTypes.number])
}))
}),
/**
* Fires event when a user clicks outside from the component.
*/
onSearch: PropTypes.func,
/**
* Fires event when user clicks on outside of component.
*/
onOutsideClick: PropTypes.func,
/**
* If search field is empty, initialDataDescription is describing witch data is showing by default for example (Recently modified data).
*/
initialDataDescription: PropTypes.string,
/**
* If search field is empty, will show initialData for example (Recently modified data).
*/
initialData: PropTypes.arrayOf(PropTypes.shape({
icon: PropTypes.string,
id: PropTypes.string,
title: PropTypes.string,
type: PropTypes.string,
name: PropTypes.string,
date: PropTypes.shape({
labelText: PropTypes.string,
date: PropTypes.oneOfType([PropTypes.instanceOf(dayjs), PropTypes.instanceOf(Date), PropTypes.string, PropTypes.number])
}),
actions: PropTypes.arrayOf(PropTypes.shape({
name: PropTypes.string,
icon: PropTypes.string.isRequired,
onClick: PropTypes.func,
description: PropTypes.string
}))
})),
/**
* if hasActive hasActiveShowMore is true you will see show more link under search result
*/
hasActiveShowMore: PropTypes.bool,
/**
* text for link under search result
*/
showMoreText: PropTypes.string,
/**
* To control showMore loading state
*/
showMoreIsLoading: PropTypes.bool,
/**
* Fires an event when clicked on link under search result
*/
onShowMoreClick: PropTypes.func,
/**
* search loading state
*/
isSearchLoading: PropTypes.bool,
/**
* total count of data to show in badge
*/
totalCount: PropTypes.number,
/**
* total max count of data to show totalCountMax+ in badge
*/
totalCountMax: PropTypes.number,
/**
* label text for badge component
*/
totalCountText: PropTypes.string,
/**
* data structure
* */
data: PropTypes.arrayOf(PropTypes.shape({
icon: PropTypes.string,
id: PropTypes.string,
title: PropTypes.string,
type: PropTypes.string,
name: PropTypes.string,
date: PropTypes.shape({
labelText: PropTypes.string,
date: PropTypes.oneOfType([PropTypes.instanceOf(dayjs), PropTypes.instanceOf(Date), PropTypes.string, PropTypes.number])
}),
actions: PropTypes.arrayOf(PropTypes.shape({
name: PropTypes.string,
icon: PropTypes.string.isRequired,
onClick: PropTypes.func,
description: PropTypes.string
}))
})),
/**
* text for no data to display
*/
noDataText: PropTypes.string,
/**
* A boolean prop to control the popover's open and close state.
*/
isOpen: PropTypes.bool
};
AdvancedSearch.defaultProps = {
onSearch: noop,
openedInputWidth: 65,
onShowMoreClick: noop,
onOutsideClick: noop,
closedInputWidth: '200px',
hasActiveShowMore: false,
showMoreIsLoading: false,
showMoreText: 'Show more',
noDataText: 'No Data to Display',
position: advancedSearchConfig.positions.right,
initialDataDescription: 'initial data description'
};
export { AdvancedSearch as default };