UNPKG

@gravity-ui/uikit

Version:

Gravity UI base styling and components

204 lines (203 loc) 11.7 kB
'use client'; "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.TableColumnSetup = void 0; const tslib_1 = require("tslib"); const react_1 = require("react"); const jsx_runtime_1 = require("react/jsx-runtime"); const React = tslib_1.__importStar(require("react")); const icons_1 = require("@gravity-ui/icons"); const react_beautiful_dnd_1 = require("react-beautiful-dnd"); const hooks_1 = require("../../../../../hooks/index.js"); const useActionHandlers_1 = require("../../../../../hooks/useActionHandlers/useActionHandlers.js"); const Button_1 = require("../../../../Button/index.js"); const Icon_1 = require("../../../../Icon/index.js"); const Text_1 = require("../../../../Text/index.js"); const TreeSelect_1 = require("../../../../TreeSelect/TreeSelect.js"); const TextInput_1 = require("../../../../controls/TextInput/index.js"); const Flex_1 = require("../../../../layout/Flex/Flex.js"); const useList_1 = require("../../../../useList/index.js"); const cn_1 = require("../../../../utils/cn.js"); const i18n_1 = tslib_1.__importDefault(require("./i18n/index.js")); require("./TableColumnSetup.css"); const b = (0, cn_1.block)('inner-table-column-setup'); const controlsCn = b('controls'); const filterInputCn = b('filter-input'); const emptyPlaceholderCn = b('empty-placeholder'); const reorderArray = (list, startIndex, endIndex) => { const result = [...list]; const [removed] = result.splice(startIndex, 1); result.splice(endIndex, 0, removed); return result; }; const prepareStickyState = (itemsById, visibleFlattenIds) => { let lastStickyStartIdx = 0; for (; lastStickyStartIdx !== visibleFlattenIds.length; lastStickyStartIdx++) { const visibleFlattenId = visibleFlattenIds[lastStickyStartIdx]; const item = itemsById[visibleFlattenId]; if (item?.sticky !== 'left' && item?.sticky !== 'start') { break; } } let firstStickyEndIdx = visibleFlattenIds.length; for (; firstStickyEndIdx !== 0; firstStickyEndIdx--) { const visibleFlattenId = visibleFlattenIds[firstStickyEndIdx - 1]; const item = itemsById[visibleFlattenId]; if (item?.sticky !== 'right' && item?.sticky !== 'end') { break; } } return { stickyStartItemIdList: visibleFlattenIds.slice(0, lastStickyStartIdx), sortableItemIdList: visibleFlattenIds.slice(lastStickyStartIdx, firstStickyEndIdx), stickyEndItemIdList: visibleFlattenIds.slice(firstStickyEndIdx), }; }; const prepareValue = (tableColumnItems) => { const selectedIds = []; tableColumnItems.forEach(({ id, isSelected }) => { if (isSelected) { selectedIds.push(id); } }); return selectedIds; }; const RENDER_DRAG_DISABLED_CONTAINER_PROPS = { isDragDisabled: true }; const useDndRenderContainer = ({ onDragEnd, renderControls }) => { const uniqId = (0, hooks_1.useUniqId)(); const dndRenderContainer = ({ renderItem, list, containerRef, id, className, }) => { const renderDndActiveItem = (provided, snapshot, rubric) => { const renderContainerProps = { provided, snapshot, }; return renderItem(list.structure.visibleFlattenIds[rubric.source.index], rubric.source.index, renderContainerProps); }; const { stickyStartItemIdList, sortableItemIdList, stickyEndItemIdList } = prepareStickyState(list.structure.itemsById, list.structure.visibleFlattenIds); const stickyStartItemList = stickyStartItemIdList.map((visibleFlattenId, idx) => { return renderItem(visibleFlattenId, idx, RENDER_DRAG_DISABLED_CONTAINER_PROPS); }); const sortableItemList = sortableItemIdList.map((visibleFlattenId, idx) => { return renderItem(visibleFlattenId, idx + stickyStartItemIdList.length); }); const stickyEndItemList = stickyEndItemIdList.map((visibleFlattenId, idx) => { return renderItem(visibleFlattenId, stickyStartItemList.length + sortableItemList.length + idx, RENDER_DRAG_DISABLED_CONTAINER_PROPS); }); return ((0, jsx_runtime_1.jsxs)(React.Fragment, { children: [(0, jsx_runtime_1.jsxs)(useList_1.ListContainerView, { ref: containerRef, id: id, className: className, children: [stickyStartItemList, (0, jsx_runtime_1.jsx)(react_beautiful_dnd_1.DragDropContext, { onDragEnd: onDragEnd, children: (0, jsx_runtime_1.jsx)(react_beautiful_dnd_1.Droppable, { droppableId: uniqId, renderClone: renderDndActiveItem, children: (droppableProvided) => { return ((0, jsx_runtime_1.jsxs)("div", { ...droppableProvided.droppableProps, ref: droppableProvided.innerRef, children: [sortableItemList, droppableProvided.placeholder] })); } }) }), stickyEndItemList] }), (0, jsx_runtime_1.jsx)("div", { className: controlsCn, children: renderControls() })] })); }; return dndRenderContainer; }; const useDndRenderItem = (sortable) => { const renderDndItem = ({ data: item, props, index, renderContainerProps, }) => { const isDragDisabled = sortable === false || renderContainerProps?.isDragDisabled === true; const endSlot = isDragDisabled ? undefined : (0, jsx_runtime_1.jsx)(Icon_1.Icon, { data: icons_1.Grip, size: 16 }); const startSlot = item.isRequired ? (0, jsx_runtime_1.jsx)(Icon_1.Icon, { data: icons_1.Lock }) : undefined; const selected = item.isRequired ? false : props.selected; const commonProps = { ...props, selected, selectionViewType: item.isRequired ? 'single' : 'multiple', content: { ...props.content, startSlot, endSlot, }, }; if (isDragDisabled) { return (0, react_1.createElement)(useList_1.ListItemView, { ...commonProps, key: commonProps.id }); } const renderItem = (provided, snapshot) => ((0, jsx_runtime_1.jsx)(useList_1.ListItemView, { ...commonProps, ...provided.draggableProps, ...provided.dragHandleProps, ref: provided.innerRef, dragging: snapshot.isDragging })); if (renderContainerProps?.provided && renderContainerProps.snapshot) { return renderItem(renderContainerProps.provided, renderContainerProps.snapshot); } return ((0, jsx_runtime_1.jsx)(react_beautiful_dnd_1.Draggable, { draggableId: props.id, index: index, isDragDisabled: isDragDisabled, children: renderItem }, `item-key-${props.id}`)); }; return renderDndItem; }; const mapItemDataToContentProps = (item) => { return { title: item.title, }; }; const defaultFilterSettingsFn = (value, item) => { return typeof item.title === 'string' ? item.title.toLowerCase().includes(value.trim().toLowerCase()) : true; }; const useEmptyRenderContainer = (placeholder) => { const emptyRenderContainer = () => (0, jsx_runtime_1.jsx)(Text_1.Text, { className: emptyPlaceholderCn, children: placeholder }); return emptyRenderContainer; }; const TableColumnSetup = (props) => { const { renderSwitcher, popupWidth, popupPlacement, items: propsItems, onUpdate: propsOnUpdate, sortable, renderControls, className, defaultItems = propsItems, showResetButton: propsShowResetButton, filterable, filterPlaceholder, filterEmptyMessage, filterSettings = defaultFilterSettingsFn, } = props; const [open, setOpen] = React.useState(false); const [sortingEnabled, setSortingEnabled] = React.useState(sortable); const [prevSortingEnabled, setPrevSortingEnabled] = React.useState(sortable); if (sortable !== prevSortingEnabled) { setPrevSortingEnabled(sortable); setSortingEnabled(sortable); } const [items, setItems] = React.useState(propsItems); const [prevPropsItems, setPrevPropsItems] = React.useState(propsItems); if (propsItems !== prevPropsItems) { setPrevPropsItems(propsItems); setItems(propsItems); } const filterState = (0, useList_1.useListFilter)({ items, filterItem: filterSettings, debounceTimeout: 0 }); const onApply = () => { const newSettings = items.map(({ id, isSelected }) => ({ id, isSelected })); propsOnUpdate(newSettings); onOpenChange(false); }; const DefaultApplyButton = () => ((0, jsx_runtime_1.jsx)(Button_1.Button, { view: "action", width: "max", onClick: onApply, children: (0, i18n_1.default)('button_apply') })); const onDragEnd = ({ destination, source }) => { if (destination?.index !== undefined && destination?.index !== source.index) { setItems((prevItems) => { return reorderArray(prevItems, source.index, destination.index); }); } }; const showResetButton = typeof propsShowResetButton === 'function' ? propsShowResetButton(items) : propsShowResetButton; const dndRenderContainer = useDndRenderContainer({ onDragEnd, renderControls: () => renderControls ? (renderControls({ DefaultApplyButton, onApply })) : ((0, jsx_runtime_1.jsxs)(Flex_1.Flex, { gapRow: 1, direction: "column", className: controlsCn, children: [showResetButton && ((0, jsx_runtime_1.jsx)(Button_1.Button, { onClick: () => { setItems(defaultItems); }, width: "max", children: (0, i18n_1.default)('button_reset') })), (0, jsx_runtime_1.jsx)(DefaultApplyButton, {})] })), }); const dndRenderItem = useDndRenderItem(sortingEnabled); const renderControl = ({ toggleOpen }) => { const onKeyDown = (0, useActionHandlers_1.createOnKeyDownHandler)(toggleOpen); return (renderSwitcher?.({ onClick: toggleOpen, onKeyDown }) || ((0, jsx_runtime_1.jsxs)(Button_1.Button, { onClick: toggleOpen, onKeyDown: onKeyDown, children: [(0, jsx_runtime_1.jsx)(Icon_1.Icon, { data: icons_1.Gear }), (0, i18n_1.default)('button_switcher')] }))); }; const onOpenChange = (open) => { setOpen(open); if (open === false) { setItems(propsItems); setSortingEnabled(sortable); filterState.reset(); } }; const onUpdate = (selectedItemsIds) => { setItems((prevItems) => { return prevItems.map((item) => ({ ...item, isSelected: item.isRequired || selectedItemsIds.includes(item.id), })); }); }; const value = React.useMemo(() => prepareValue(items), [items]); const emptyRenderContainer = useEmptyRenderContainer(filterEmptyMessage); const onFilterValueUpdate = (value) => { filterState.onFilterUpdate(value); setSortingEnabled(!value.length); }; const slotBeforeListBody = filterable ? ((0, jsx_runtime_1.jsx)(TextInput_1.TextInput, { size: "m", view: "clear", placeholder: filterPlaceholder, value: filterState.filter, className: filterInputCn, onUpdate: onFilterValueUpdate, hasClear: true })) : null; const renderContainer = filterState.filter && !filterState.items.length ? emptyRenderContainer : dndRenderContainer; return ((0, jsx_runtime_1.jsx)(TreeSelect_1.TreeSelect, { className: b(null, className), mapItemDataToContentProps: mapItemDataToContentProps, multiple: true, size: "l", open: open, value: value, items: filterState.filter ? filterState.items : items, onUpdate: onUpdate, popupWidth: popupWidth, onOpenChange: onOpenChange, placement: popupPlacement, slotBeforeListBody: slotBeforeListBody, renderContainer: renderContainer, renderControl: renderControl, renderItem: dndRenderItem })); }; exports.TableColumnSetup = TableColumnSetup; //# sourceMappingURL=TableColumnSetup.js.map