UNPKG

@dnb/eufemia

Version:

DNB Eufemia Design System UI Library

124 lines (123 loc) 5.75 kB
"use client"; import _extends from "@babel/runtime-corejs3/helpers/esm/extends"; import React, { useCallback, useContext, useRef, useState } from 'react'; import classnames from 'classnames'; import ScrollView from "../../fragments/scroll-view/ScrollView.js"; import { useIsomorphicLayoutEffect as useLayoutEffect } from "../../shared/helpers/useIsomorphicLayoutEffect.js"; import { ListContext } from "./ListContext.js"; const defaultListItemOutlineCompensation = '0.125rem'; function ListScrollView(props) { var _parentContext$varian, _parentContext$separa; const parentContext = useContext(ListContext); const { className, children, maxVisibleListItems, skeleton, disabled, style, innerRef, ...rest } = props; const localRef = useRef(null); const [measuredMaxHeight, setMeasuredMaxHeight] = useState(undefined); const [outlineCompensation, setOutlineCompensation] = useState(defaultListItemOutlineCompensation); const hasValidMaxVisibleListItems = typeof maxVisibleListItems === 'number' && Number.isFinite(maxVisibleListItems) && maxVisibleListItems > 0; const fallbackMaxHeight = hasValidMaxVisibleListItems ? `calc(var(--item-height, 4rem) * ${maxVisibleListItems})` : undefined; const measureMaxHeight = useCallback(() => { if (!hasValidMaxVisibleListItems || style !== null && style !== void 0 && style.maxHeight) { setMeasuredMaxHeight(undefined); return; } setOutlineCompensation(getListItemOutlineCompensation(localRef.current)); const measuredHeight = getVisibleListItemsHeight(localRef.current, maxVisibleListItems); setMeasuredMaxHeight(measuredHeight ? `${measuredHeight}px` : undefined); }, [hasValidMaxVisibleListItems, maxVisibleListItems, style === null || style === void 0 ? void 0 : style.maxHeight]); useLayoutEffect(() => { if (!innerRef) { return; } if (typeof innerRef === 'function') { innerRef(localRef.current); return; } innerRef.current = localRef.current; }, [innerRef]); useLayoutEffect(() => { measureMaxHeight(); }, [children, measureMaxHeight]); useLayoutEffect(() => { if (!hasValidMaxVisibleListItems || style !== null && style !== void 0 && style.maxHeight) { return; } window.addEventListener('resize', measureMaxHeight); return () => { window.removeEventListener('resize', measureMaxHeight); }; }, [hasValidMaxVisibleListItems, measureMaxHeight, style === null || style === void 0 ? void 0 : style.maxHeight]); const resolvedMaxHeight = style !== null && style !== void 0 && style.maxHeight ? undefined : measuredMaxHeight || fallbackMaxHeight; const scrollViewStyle = { ...(resolvedMaxHeight ? { maxHeight: `calc(${resolvedMaxHeight} + ${outlineCompensation})`, marginBottom: `-${outlineCompensation}` } : null), ...style }; const scrollViewContent = React.createElement(ScrollView, _extends({ className: classnames("dnb-list__card__scroll-view dnb-list--inset-outline", className), interactive: "auto", ref: localRef, style: scrollViewStyle }, rest), children); const appliedSkeleton = skeleton !== null && skeleton !== void 0 ? skeleton : parentContext === null || parentContext === void 0 ? void 0 : parentContext.skeleton; const appliedDisabled = disabled !== null && disabled !== void 0 ? disabled : parentContext === null || parentContext === void 0 ? void 0 : parentContext.disabled; return React.createElement(ListContext.Provider, { value: { variant: (_parentContext$varian = parentContext === null || parentContext === void 0 ? void 0 : parentContext.variant) !== null && _parentContext$varian !== void 0 ? _parentContext$varian : 'basic', separated: (_parentContext$separa = parentContext === null || parentContext === void 0 ? void 0 : parentContext.separated) !== null && _parentContext$separa !== void 0 ? _parentContext$separa : false, skeleton: appliedSkeleton, disabled: appliedDisabled } }, scrollViewContent); } function getVisibleListItemsHeight(scrollViewElement, maxVisibleListItems) { if (!scrollViewElement) { return null; } const listElement = scrollViewElement.querySelector('.dnb-list__container'); if (!(listElement instanceof HTMLElement)) { return null; } const items = Array.from(listElement.children).filter(element => element instanceof HTMLElement); const firstVisibleItem = items[0]; const lastVisibleItem = items[maxVisibleListItems - 1]; if (!firstVisibleItem || !lastVisibleItem) { return null; } return Math.ceil(lastVisibleItem.offsetTop + lastVisibleItem.offsetHeight - firstVisibleItem.offsetTop); } function getListItemOutlineCompensation(scrollViewElement) { if (!scrollViewElement || typeof getComputedStyle === 'undefined') { return defaultListItemOutlineCompensation; } const cardElement = scrollViewElement.closest('.dnb-card'); const targetElement = (cardElement === null || cardElement === void 0 ? void 0 : cardElement.querySelector('.dnb-list__container')) || scrollViewElement.querySelector('.dnb-list__container'); if (!(targetElement instanceof HTMLElement)) { return defaultListItemOutlineCompensation; } const outlineWidth = getComputedStyle(targetElement).getPropertyValue('--item-outline-width').trim(); return doubleCssLength(outlineWidth) || defaultListItemOutlineCompensation; } function doubleCssLength(value) { if (!value) { return null; } const match = value.match(/^(-?\d*\.?\d+)([a-z%]+)$/i); if (match) { return `${parseFloat(match[1]) * 2}${match[2]}`; } return `calc(${value} * 2)`; } ListScrollView._supportsSpacingProps = true; export default ListScrollView; //# sourceMappingURL=ListScrollView.js.map