UNPKG

@gravity-ui/uikit

Version:

Gravity UI base styling and components

187 lines (186 loc) 6.7 kB
import { jsx as _jsx } from "react/jsx-runtime"; import * as React from 'react'; import { KeyCode } from "../../constants.js"; import { FLATTEN_KEY, GROUP_ITEM_MARGIN_TOP, MOBILE_ITEM_HEIGHT, SIZE_TO_ITEM_HEIGHT, } from "./constants.js"; export const isSelectGroupTitle = (option) => { return Boolean(option && 'label' in option); }; export const getFlattenOptions = (options) => { const flatten = options.reduce((acc, option) => { if ('label' in option) { acc.push({ label: option.label, disabled: true, data: option.data }); acc.push(...(option.options || [])); } else { acc.push(option); } return acc; }, []); Object.defineProperty(flatten, FLATTEN_KEY, { enumerable: false, value: {}, }); return flatten; }; export const getPopupItemHeight = (args) => { const { getOptionHeight, getOptionGroupHeight, size, option, index, mobile } = args; let itemHeight = mobile ? MOBILE_ITEM_HEIGHT : SIZE_TO_ITEM_HEIGHT[size]; if (isSelectGroupTitle(option)) { const marginTop = index === 0 ? 0 : GROUP_ITEM_MARGIN_TOP; itemHeight = option.label === '' ? 0 : itemHeight; return getOptionGroupHeight ? getOptionGroupHeight(option, index) : itemHeight + marginTop; } return getOptionHeight ? getOptionHeight(option, index) : itemHeight; }; export const getOptionsHeight = (args) => { const { getOptionHeight, getOptionGroupHeight, size, options, mobile } = args; return options.reduce((height, option, index) => { return (height + getPopupItemHeight({ getOptionHeight, getOptionGroupHeight, size, option, index, mobile })); }, 0); }; const getOptionText = (option) => { if (typeof option.content === 'string') { return option.content; } if (typeof option.children === 'string') { return option.children; } if (option.text) { return option.text; } return option.value; }; export const getSelectedOptionsContent = (options, value, renderSelectedOption) => { if (value.length === 0) { return null; } const flattenSimpleOptions = options.filter((opt) => !isSelectGroupTitle(opt)); const selectedOptions = value.reduce((acc, val) => { const selectedOption = flattenSimpleOptions.find((opt) => opt.value === val); acc.push(selectedOption || { value: val }); return acc; }, []); if (renderSelectedOption) { return selectedOptions.map((option, index) => { return (_jsx(React.Fragment, { children: renderSelectedOption(option, index) }, option.value)); }); } else { return selectedOptions .map((option) => { return getOptionText(option); }) .join(', '); } }; const getTypedChildrenArray = (children) => { return React.Children.toArray(children); }; const getOptionsFromOptgroupChildren = (children) => { return React.Children.toArray(children).reduce((acc, { props }) => { if ('value' in props) { acc.push(props); } return acc; }, []); }; export const getOptionsFromChildren = (children) => { return getTypedChildrenArray(children).reduce((acc, { props }) => { if ('label' in props) { const options = props.options || getOptionsFromOptgroupChildren(props.children); acc.push({ options, label: props.label, }); } if ('value' in props) { acc.push({ ...props }); } return acc; }, []); }; export const getNextQuickSearch = (keyCode, quickSearch) => { // https://www.w3.org/TR/uievents-code/#key-alphanumeric-writing-system const writingSystemKeyPressed = keyCode.length === 1; const backspacePressed = keyCode === KeyCode.BACKSPACE; let nextQuickSearch = ''; if (backspacePressed && quickSearch.length) { nextQuickSearch = quickSearch.slice(0, quickSearch.length - 1); } else if (writingSystemKeyPressed) { nextQuickSearch = (quickSearch + keyCode).trim(); } return nextQuickSearch; }; const getEscapedRegExp = (string) => { return new RegExp(string.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&'), 'i'); }; export const findItemIndexByQuickSearch = (quickSearch, items) => { if (!items) { return -1; } return items.findIndex((item) => { if (isSelectGroupTitle(item)) { return false; } if (item.disabled) { return false; } const optionText = getOptionText(item); return getEscapedRegExp(quickSearch).test(optionText); }); }; export const getListItems = (listRef) => { return listRef?.current?.getItems() || []; }; export const getActiveItem = (listRef) => { const items = getListItems(listRef); const activeItemIndex = listRef?.current?.getActiveItem(); return typeof activeItemIndex === 'number' ? items[activeItemIndex] : undefined; }; const isOptionMatchedByFilter = (option, filter) => { const lowerOptionText = getOptionText(option).toLocaleLowerCase(); const lowerFilter = filter.toLocaleLowerCase(); return lowerOptionText.indexOf(lowerFilter) !== -1; }; export const getFilteredFlattenOptions = (args) => { const { options, filter, filterOption } = args; const filteredOptions = options.filter((option) => { if (isSelectGroupTitle(option)) { return true; } return filterOption ? filterOption(option, filter) : isOptionMatchedByFilter(option, filter); }); return filteredOptions.reduce((acc, option, index) => { const groupTitle = isSelectGroupTitle(option); const previousGroupTitle = isSelectGroupTitle(acc[acc.length - 1]); const isLastOption = index === filteredOptions.length - 1; if (groupTitle && previousGroupTitle) { acc.pop(); } if (!groupTitle || (groupTitle && !isLastOption)) { acc.push(option); } return acc; }, []); }; export function scrollToItem(node) { const container = node.offsetParent; if (container instanceof HTMLElement) { const height = container.offsetHeight; const scrollTop = container.scrollTop; const top = node.offsetTop; const bottom = top + node.offsetHeight; if (bottom >= scrollTop + height) { container.scrollTo({ top: top - height + node.offsetHeight }); } else if (top <= scrollTop) { container.scrollTo({ top }); } } return true; } //# sourceMappingURL=utils.js.map