UNPKG

@geneui/components

Version:

The Gene UI components library designed for BI tools

663 lines (656 loc) 24 kB
import { _ as _extends } from '../_rollupPluginBabelHelpers-e8fb2e5c.js'; import React__default, { useRef, useState, useMemo, useCallback, useEffect } from 'react'; import PropTypes from 'prop-types'; import { c as classnames } from '../index-031ff73c.js'; import ModuleTitle from '../ModuleTitle/index.js'; import Paper from '../Paper/index.js'; import { D as Dropdown, I as InfiniteLoader, W as WindowScroller, L as List, C as CellMeasurer } from '../index-9d8d0112.js'; import { C as CellMeasurerCache } from '../CellMeasurerCache-661c24a8.js'; import { o as oneIsRequired, n as noop } from '../index-a0e4e333.js'; import BusyLoader from '../BusyLoader/index.js'; import Empty from '../Empty/index.js'; import Icon from '../Icon/index.js'; import Widget from '../Widget/index.js'; import Card from '../Card/index.js'; import { s as styleInject } from '../style-inject.es-746bb8ed.js'; import '../configs-00612ce0.js'; import '../index-6d7e99cd.js'; import '../tslib.es6-f211516f.js'; import 'react-dom'; import '../dateValidation-67caec66.js'; import '../_commonjsHelpers-24198af3.js'; import '../hooks/useDeviceType.js'; import '../hooks/useWindowSize.js'; import '../hooks/useDebounce.js'; import '../GeneUIProvider/index.js'; import '../objectWithoutPropertiesLoose-d8a4a68c.js'; import '../react-lifecycles-compat.es-6e1f3768.js'; import '../clsx.m-2bb6df4b.js'; import '../hooks/useMount.js'; import '../hooks/useClick.js'; import '../hooks/useKeyDown.js'; import '../hooks/useClickOutside.js'; import '../hooks/useUpdatableRef.js'; import '../hooks/useForceUpdate.js'; import '../useEllipsisDetection-4d997d5d.js'; import '../index-08898b29.js'; import '../index-122432cd.js'; import '../Scrollbar/index.js'; import '../debounce-4419bc2f.js'; import '../ExtendedInput/index.js'; import '../SuggestionList/index.js'; import '../config-1053d64d.js'; import '../callAfterDelay-7272faca.js'; import '../Checkbox/index.js'; import '../checkboxRadioSwitcher-5b69d7bd.js'; import '../guid-8ddf77b3.js'; import '../index-0cbb1102.js'; import '../Tag/index.js'; import '../KeyValue/index.js'; import '../hooks/useBodyScroll.js'; import '../Button/index.js'; import '../MobilePopup/index.js'; import '../Portal/index.js'; import '../Popover/index.js'; import '../Menu/index.js'; import '../Option/index.js'; import '../SkeletonLoader/index.js'; function WithTitle(_ref) { let { name, actions, children, ...restProps } = _ref; return /*#__PURE__*/React__default.createElement(React__default.Fragment, null, /*#__PURE__*/React__default.createElement(ModuleTitle, _extends({ title: name, cornerRadius: "position-radius" }, restProps), actions), children); } WithTitle.propTypes = { name: PropTypes.oneOfType([PropTypes.string, PropTypes.node]).isRequired, actions: PropTypes.node, children: PropTypes.node }; function PaperWrapper(_ref) { let { paperDirection, cornerRadius, className, children, shadow, ...restProps } = _ref; return /*#__PURE__*/React__default.createElement(Paper, _extends({ shadow: shadow, paperDirection: paperDirection, cornerRadius: cornerRadius, className: className }, restProps), children); } PaperWrapper.propTypes = { className: PropTypes.string, children: PropTypes.node.isRequired, cornerRadius: PropTypes.string, shadow: PropTypes.bool, ...Paper.propTypes }; PaperWrapper.defaultProps = { shadow: false, cornerRadius: 'full-radius', paperDirection: 'column' }; var css_248z = "[data-gene-ui-version=\"2.16.5\"] .mobile-table-holder{position:relative;width:100%}[data-gene-ui-version=\"2.16.5\"] .paper>.mobile-table-holder{padding:1.6rem}[data-gene-ui-version=\"2.16.5\"] .m-popup-content>.paper>.mobile-table-holder{padding:1.6rem 0}[data-gene-ui-version=\"2.16.5\"] .mobile-table-head{margin:0 0 1rem;width:100%}[data-gene-ui-version=\"2.16.5\"] .mobile-table-head>ul{align-items:center;display:flex;width:100%}[data-gene-ui-version=\"2.16.5\"] .mobile-table-head>ul>li{align-items:center;display:flex;flex-shrink:0}[data-gene-ui-version=\"2.16.5\"] .mobile-table-head>ul>li+li{margin:0 0 0 3rem}[data-gene-ui-version=\"2.16.5\"] .mobile-table-head>ul>li:nth-child(2){flex:auto;max-width:20rem}[data-gene-ui-version=\"2.16.5\"] .mt-results-holder{font:600 1.4rem/1.8rem var(--font-family);opacity:.7;padding:0 1rem}[data-gene-ui-version=\"2.16.5\"] .mt-results-holder:not(:first-child){margin:1.6rem 0 0}[data-gene-ui-version=\"2.16.5\"] .mobile-table-cc{margin-inline-end:3rem;width:19.6rem}[data-gene-ui-version=\"2.16.5\"] .mobile-sort-button{align-items:center;cursor:pointer;display:flex;font:600 1.4rem/2.4rem var(--font-family)}[data-gene-ui-version=\"2.16.5\"] .mobile-sort-button p{transition:color .4s}[data-gene-ui-version=\"2.16.5\"] .mobile-sort-button .active{color:var(--hero)}[data-gene-ui-version=\"2.16.5\"] .mobile-sort-icons{height:2.4rem;margin-inline-start:1.2rem;position:relative;width:2.4rem}[data-gene-ui-version=\"2.16.5\"] .mobile-sort-icons .icon{left:0;position:absolute;top:0;transition:color .4s}[data-gene-ui-version=\"2.16.5\"] .mobile-sort-icons .icon:not(.active){color:rgba(var(--background-sc-rgb),.5)}[data-gene-ui-version=\"2.16.5\"] .mobile-table-body{width:100%}[data-gene-ui-version=\"2.16.5\"] .mobile-table-body .ReactVirtualized__Grid,[data-gene-ui-version=\"2.16.5\"] .mobile-table-body .ReactVirtualized__Grid__innerScrollContainer{overflow:visible!important}[data-gene-ui-version=\"2.16.5\"] .mobile-table-loading{align-items:center;display:flex;justify-content:center;padding:2.4rem 0;width:100%}[data-gene-ui-version=\"2.16.5\"] .mobile-table-loading.absolute-splash{background:rgba(var(--background-rgb),.6);height:100%;left:0;position:absolute;top:0}[data-gene-ui-version=\"2.16.5\"] .cards-empty-holder{align-items:center;display:flex;height:calc(100vh - 35.7rem);justify-content:center;width:100%}[data-gene-ui-version=\"2.16.5\"] .quick-view-holder{padding:1.6rem 0;width:100%}[data-gene-ui-version=\"2.16.5\"] .quick-view-holder>.card-list-col{grid-column-gap:3.8rem;align-items:center;display:grid;font:600 1.4rem/2.2rem var(--font-family);grid-template-columns:1fr 1fr}[data-gene-ui-version=\"2.16.5\"] .quick-view-holder>.card-list-col+.card-list-col{margin:2rem 0 0}[data-gene-ui-version=\"2.16.5\"] .quick-view-holder>.card-list-col .kv-label{opacity:.7}[data-gene-ui-version=\"2.16.5\"] .quick-view-holder>.card-list-col .kv-value{white-space:normal;word-break:break-word}[data-gene-ui-version=\"2.16.5\"] .quick-view-holder a:not([class]){color:var(--hero)}[data-gene-ui-version=\"2.16.5\"] .mc-widgets-holder{-webkit-overflow-scrolling:auto;margin:0 -1.6rem;overflow-x:auto;overflow-y:hidden;padding:0 1.6rem 1.6rem;width:calc(100% + 3.2rem)}[data-gene-ui-version=\"2.16.5\"] .mc-widgets-holder>ul{align-items:center;display:flex;min-width:100%}[data-gene-ui-version=\"2.16.5\"] .mc-widgets-holder>ul>li{margin-inline-end:1rem}[data-gene-ui-version=\"2.16.5\"] .mc-widgets-holder+.mobile-table-head{border-top:1px solid rgba(var(--background-sc-rgb),.1);padding:1.6rem 0 0}"; styleInject(css_248z); const defaultSortFn = (prev, next, dataKey, type) => { const first = prev.data[dataKey]; const second = next.data[dataKey]; if (first === null) return 1; if (second === null) return -1; const firstLowerCased = typeof first === 'string' ? first.toLowerCase() : first; const secondLowerCased = typeof second === 'string' ? second.toLowerCase() : second; if (type === 'asc') { return firstLowerCased > secondLowerCased ? 1 : -1; } if (type === 'desc') { return firstLowerCased > secondLowerCased ? -1 : 1; } return 0; }; function CardList(props) { const { rowClassName, onPaginationChange, shadow, border, sortableColumns, rowKey, sortedColumn, sortType, defaultSortedColumn, defaultSortType, onSortChange, columnLimit, resultText, className, loading, rows, rowsCount, columns, columnKey, rowActionBar, getPopupProps, customSubHeader, rowsPerPage, sortingPlaceholder, viewCardText, expandText, cancelText, sortByText, expandedText, emptyContent, expandedCloseText, scrollElement, renderRowNestedChildren, rowExtraClickMenuTitle, getExpandIconDisableState, onColumnChange, totals, rowExtraClick, rowExtraClickNeeded, closeWithOutsideClick, isEditMode, ...restProps } = props; const isCustomScrollElement = ('scrollElement' in props); const isSortControlled = ('onSortChange' in props); const virtualizedList = useRef(null); const [sortDir, setSortDir] = useState(defaultSortType || null); const [sortCol, setSortCol] = useState(defaultSortedColumn || null); const [page, setPage] = useState(1); const [listWidth, setListWidth] = useState(null); const [pageLoading, setPageLoading] = useState(false); const columnsWithSort = useMemo(() => columns.filter(_ref => { let { sortable } = _ref; return typeof sortable === 'boolean' ? sortable : sortableColumns; }), [columns, sortableColumns]); const sortedRows = useMemo(() => { if (isSortControlled || !sortDir) return rows; const column = columns.find(col => col.dataKey === sortCol) || {}; const sortFn = column.sortFn ? (prev, next) => column.sortFn(prev, next, sortCol, sortDir, column.formatter, column.removeSymbol) : (prev, next) => defaultSortFn(prev, next, sortCol, sortDir); if (sortDir !== null) return [...rows].sort(sortFn); return rows; }, [isSortControlled, sortDir, rows, columns, sortCol]); const handleSortChange = useCallback(() => { const dir = !sortDir ? 'asc' : sortDir === 'asc' ? 'desc' : null; const sortedColValue = isSortControlled ? sortedColumn : sortCol; const column = columns.find(col => col[columnKey] === sortedColValue) || {}; if (sortCol) { !isSortControlled && setSortDir(dir); } onSortChange && onSortChange({ column }, sortCol, dir); }, [sortDir, columns, sortCol, onSortChange, columnKey, sortedColumn, isSortControlled]); const handlePageLoad = useCallback(_ref2 => { let { stopIndex } = _ref2; const loadedCount = stopIndex + 1; if (loadedCount === rowsCount) return false; if (loadedCount === rowsPerPage * page) { const newPage = page + 1; onPaginationChange(newPage, rowsPerPage); setPageLoading(true); setPage(newPage); } }, [rowsCount, rowsPerPage, page, onPaginationChange]); useEffect(() => { if (!loading) setPageLoading(false); }, [loading]); const sortedRowsLength = sortedRows.length; const cache = useMemo(() => new CellMeasurerCache({ minHeight: 75, defaultHeight: 200, fixedWidth: true }), []); const rowRenderer = _ref3 => { let { index, style, parent } = _ref3; const { onClick, ...restItem } = sortedRows[index]; return /*#__PURE__*/React__default.createElement(CellMeasurer, { cache: cache, columnIndex: 0, key: index, parent: parent, rowIndex: index }, /*#__PURE__*/React__default.createElement(Card, _extends({}, restItem, { style: { top: style.top }, closeWithOutsideClick: closeWithOutsideClick, isCustomScrollElement: isCustomScrollElement, rowExtraClickMenuTitle: rowExtraClickMenuTitle, getExpandIconDisableState: getExpandIconDisableState, onRowClick: onClick, index: index, columnKey: columnKey, columnLimit: columnLimit, rowActionBar: rowActionBar, getPopupProps: getPopupProps, rowExtraClick: rowExtraClick, isEditMode: isEditMode, rowExtraClickNeeded: rowExtraClickNeeded, rowHeightCache: cache, row: restItem, columns: columns, className: rowClassName, shadow: shadow, border: border, virtualizedList: virtualizedList.current, viewCardText: viewCardText, expandText: expandText, cancelText: cancelText, expandedText: expandedText, expandedCloseText: expandedCloseText, renderRowNestedChildren: renderRowNestedChildren }))); }; const handleColumnChange = useCallback(_ref4 => { let { [columnKey]: value, ...rest } = _ref4; setSortCol(value); setSortDir(null); onColumnChange && onColumnChange(value, rest); }, [columnKey, onColumnChange]); const customScrollElement = isCustomScrollElement && scrollElement ? scrollElement.current : undefined; return /*#__PURE__*/React__default.createElement("div", _extends({ className: classnames('mobile-table-holder', className) }, restProps), sortedRows.length ? /*#__PURE__*/React__default.createElement(React__default.Fragment, null, customSubHeader, !!Object.keys(totals).length && /*#__PURE__*/React__default.createElement("div", { className: "mc-widgets-holder" }, /*#__PURE__*/React__default.createElement("ul", null, columns.map(_ref5 => { let { text, widgetColor, [columnKey]: unique } = _ref5; return totals[unique] && /*#__PURE__*/React__default.createElement("li", { key: unique }, /*#__PURE__*/React__default.createElement(Widget, { type: "colorful", title: text, color: widgetColor, text: totals[unique], size: "small" })); }))), /*#__PURE__*/React__default.createElement("div", { className: "mobile-table-head" }, !!columnsWithSort.length && /*#__PURE__*/React__default.createElement("ul", null, /*#__PURE__*/React__default.createElement("li", null, /*#__PURE__*/React__default.createElement("button", { className: "mobile-sort-button", onClick: handleSortChange }, /*#__PURE__*/React__default.createElement("p", { className: classnames({ active: sortDir || sortType }) }, sortByText), /*#__PURE__*/React__default.createElement("div", { className: "mobile-sort-icons" }, /*#__PURE__*/React__default.createElement(Icon, { type: "bc-icon-sorting-down", className: classnames({ active: sortDir === 'desc' || isSortControlled && sortType === 'desc' }) }), /*#__PURE__*/React__default.createElement(Icon, { type: "bc-icon-sorting-up", className: classnames({ active: sortDir === 'asc' || isSortControlled && sortType === 'asc' }) })))), /*#__PURE__*/React__default.createElement("li", null, /*#__PURE__*/React__default.createElement(Dropdown, { data: columnsWithSort, defaultValue: isSortControlled ? sortedColumn : sortCol || null, onChange: handleColumnChange, placeholder: sortingPlaceholder, labelKey: "text", valueKey: columnKey }))), /*#__PURE__*/React__default.createElement("div", { className: "mt-results-holder" }, resultText, " ", rowsCount || rows.length)), /*#__PURE__*/React__default.createElement("div", { className: "mobile-table-body", style: { height: '100%' }, ref: ref => ref && setListWidth(ref.clientWidth) }, listWidth && (!isCustomScrollElement || scrollElement.current) && /*#__PURE__*/React__default.createElement(InfiniteLoader, { minimumBatchSize: 0, threshold: 0, isRowLoaded: index => !!sortedRows[index], loadMoreRows: handlePageLoad, rowCount: sortedRowsLength }, _ref6 => { let { onRowsRendered } = _ref6; return /*#__PURE__*/React__default.createElement(WindowScroller, { scrollElement: customScrollElement }, _ref7 => { let { height = 0, scrollTop, isScrolling } = _ref7; return /*#__PURE__*/React__default.createElement(List, { ref: virtualizedList, autoHeight: true, height: height, onRowsRendered: onRowsRendered, isScrolling: isScrolling, rowCount: sortedRowsLength, rowHeight: row => cache.rowHeight(row), rowRenderer: rowRenderer, scrollTop: scrollTop, width: listWidth }); }); }))) : /*#__PURE__*/React__default.createElement("div", { className: "cards-empty-holder" }, emptyContent), loading && /*#__PURE__*/React__default.createElement("div", { className: classnames('mobile-table-loading', { 'absolute-splash': !pageLoading }) }, /*#__PURE__*/React__default.createElement(BusyLoader, { spinnerSize: pageLoading ? 'big' : 'small' }))); } CardList.propTypes = { /** * Show busy wrapper */ loading: PropTypes.bool, /** * Is have shadow */ shadow: PropTypes.bool, /** * Is have border */ border: PropTypes.bool, /** * Is card in edit mode */ isEditMode: PropTypes.bool, /** * Text for showing result */ resultText: PropTypes.string, /** * Classname for card items */ rowClassName: PropTypes.string, /** * Classname for card list */ className: PropTypes.string, /** * Type of sorting when it's controlled */ sortType: PropTypes.oneOf(['asc', 'desc', null]), /** * DataKey of column which was sorted */ sortedColumn: PropTypes.string, /** * DataKey of column which was sorted by default */ defaultSortedColumn: PropTypes.string, /** * Type of default sorting */ defaultSortType: PropTypes.oneOf(['asc', 'desc', null]), /** * Title for rowExtraClick menu item */ rowExtraClickMenuTitle: PropTypes.string, /** * Function which should return boolean */ getExpandIconDisableState: PropTypes.func, /** * Custom elements for sub header */ customSubHeader: PropTypes.node, /** * Are columns sortable? */ sortableColumns: PropTypes.bool, /** * Pass this function to catch sorting event and get related data * ((type: string, dataKey: sting, column: PropTypes.columns[item]) => void */ onSortChange: PropTypes.func, /** * Placeholder for sorting dropdown */ sortingPlaceholder: PropTypes.string, /** * sortFn: Custom sort function for columns.((prev: PropTypes.rows[item], next: PropTypes.rows[item], rows: PropTypes.rows, dataKey: string) => { * if (prev is less than next by some ordering criterion) { * return -1; * } * if (prev is greater than next by the ordering criterion) { * return 1; * } * prev is equal to next * return 0; * } * }) * * text: Text value for columns * * render: Function to render custom text.((column: PropTypes.columns[item], index: number, isEditActive: boolean) => return any) * * sortable: Allows sorting if true * * resizable: Allows resizing if true * * current column's data key * * draggable: Allows dragging if true * * colRenderer: Render custom component on certain column of each row. ((value: string || number, index: number, row: PropTypes.rows[item], isEditActive: boolean) => { * return <div>Hello World</div>}) * * getter: Function to define custom text. ((row: PropTypes.rows[item], index: number, isEditActive: boolean)) => { * return some string * }) * * formatter: Function tp format displaying text. ((middleText: string, row: PropTypes.rows[item], index: number, isEditActive: boolean) => { * return some string * }) * */ columns: PropTypes.arrayOf(PropTypes.shape({ sortFn: PropTypes.func, ...oneIsRequired({ text: PropTypes.node, render: PropTypes.func }), sortable: PropTypes.bool, resizable: PropTypes.bool, dataKey: PropTypes.string, draggable: PropTypes.bool, colRenderer: PropTypes.func, getter: PropTypes.func, formatter: PropTypes.func, hide: PropTypes.bool })).isRequired, /** * Key from column's data which value is surely unique */ columnKey: PropTypes.string.isRequired, /** * hasHover: Allow hovering * data: rows column's data * nestedTable: object of columns: array of objects and rows: array of objects * className: additional className for row element * render: Render custom component on (row: PropTypes.rows[item] index: number) => { * return <div>Hello World</div>}) */ rows: PropTypes.arrayOf(PropTypes.shape({ /** * Expand button disabled state */ expandDisabled: PropTypes.bool, data: PropTypes.object, className: PropTypes.string, render: PropTypes.func })), /** * Rows total count */ rowsCount: PropTypes.number, /** * Number of columns that will be shown */ columnLimit: PropTypes.number, /** * Function which will return Array of objects as row's action bar on the right corner of the row. ((row: PropTypes.rows[item] ,index: number) => []) */ rowActionBar: PropTypes.func, /** * Function which will return props for mobile popup. ((row: PropTypes.rows[item] ,index: number) => {}) */ getPopupProps: PropTypes.func, /** * Text for View Card */ viewCardText: PropTypes.string, /** * Text for Expand */ expandText: PropTypes.string, /** * Text for Cancel */ cancelText: PropTypes.string, /** * Key from row's data which value is surely unique */ rowKey: PropTypes.string.isRequired, /** * Will render when there are no rows to render */ emptyContent: PropTypes.node, /** * Text for Expanded popup close button */ expandedCloseText: PropTypes.string, /** * Text for Expanded popup title */ expandedText: PropTypes.string, /** * Function which should return null or another * Function which will return valid node */ renderRowNestedChildren: PropTypes.func, /** * Function will be called when page changes (page, rowsPerPage) => void */ onPaginationChange: PropTypes.func, /** * Rows count per page */ rowsPerPage: PropTypes.number, /** * Text for sort by */ sortByText: PropTypes.string, /** * Object with dataKeys and totals */ totals: PropTypes.object, /** * Extra click function for rows. ((e: event object, data: object, index: number, row: PropTypes.rows[item]) => custom logic) */ rowExtraClick: PropTypes.func, /** * Function for determining which rows should have extra click. ((e: event object, data: object, index: number, row: PropTypes.rows[item]) => return true or false) */ rowExtraClickNeeded: PropTypes.oneOfType([PropTypes.func, PropTypes.bool]) }; CardList.defaultProps = { totals: {}, resultText: 'Result:', sortByText: 'Sort by', onPaginationChange: noop, emptyContent: /*#__PURE__*/React__default.createElement(Empty, { title: "No data to display" }), columnKey: 'dataKey', sortingPlaceholder: 'Column', rowExtraClickNeeded: noop, sortableColumns: false, columnLimit: 6, shadow: true, border: true, rowsPerPage: 20 }; function WrapperTableContainer(_ref) { let { name, titleActions, className, paperProps, withTitle, customSubHeader, ...cardProps } = _ref; return /*#__PURE__*/React__default.createElement(PaperWrapper, _extends({ className: classnames(className) }, paperProps), withTitle ? /*#__PURE__*/React__default.createElement(WithTitle, { name: name, actions: titleActions }, customSubHeader, /*#__PURE__*/React__default.createElement(CardList, cardProps)) : /*#__PURE__*/React__default.createElement(React__default.Fragment, null, customSubHeader, /*#__PURE__*/React__default.createElement(CardList, cardProps))); } WrapperTableContainer.propTypes = { /** * Module title name */ name: PropTypes.node, /** * Actions for ModuleTitle component */ titleActions: PropTypes.node, /** * Custom elements for sub header */ customSubHeader: PropTypes.node, /** * Classname for card list */ className: PropTypes.string, /** * Props for Paper component */ paperProps: PropTypes.shape({ ...PaperWrapper.propTypes }), /** * Show/Hide ModuleTitle component */ withTitle: PropTypes.bool, ...CardList.propTypes }; WrapperTableContainer.defaultProps = { ...CardList.defaultProps }; export { CardList, WrapperTableContainer as WrappedCardList };