@itwin/itwinui-react
Version:
A react component library for iTwinUI
168 lines (167 loc) • 5.37 kB
JavaScript
;
Object.defineProperty(exports, '__esModule', {
value: true,
});
Object.defineProperty(exports, 'CarouselDotsList', {
enumerable: true,
get: function () {
return CarouselDotsList;
},
});
const _interop_require_default = require('@swc/helpers/_/_interop_require_default');
const _interop_require_wildcard = require('@swc/helpers/_/_interop_require_wildcard');
const _react = /*#__PURE__*/ _interop_require_wildcard._(require('react'));
const _classnames = /*#__PURE__*/ _interop_require_default._(
require('classnames'),
);
const _CarouselContext = require('./CarouselContext.js');
const _index = require('../../utils/index.js');
const _CarouselDot = require('./CarouselDot.js');
const CarouselDotsList = _react.forwardRef((props, ref) => {
let {
currentIndex: userCurrentIndex,
length,
className,
onSlideChange,
children,
...rest
} = props;
let context = _react.useContext(_CarouselContext.CarouselContext);
let slideCount =
length ?? context?.slideCount ?? _react.Children.count(children);
let currentIndex = userCurrentIndex ?? context?.currentIndex ?? 0;
let idPrefix = props.id ?? context?.idPrefix;
let handleSlideChange = _react.useCallback(
(index) => {
if (context) {
context.setCurrentIndex(index);
context.scrollToSlide.current(index);
}
listRef.current?.children[index]?.focus();
onSlideChange?.(index);
},
[context, onSlideChange],
);
let justMounted = _react.useRef(true);
let [visibleCount, setVisibleCount] = _react.useState(slideCount);
let listRef = _react.useRef(null);
let [width, setWidth] = _react.useState();
let [resizeRef, resizeObserver] = (0, _index.useResizeObserver)(
({ width }) => {
if (!listRef.current) return;
setWidth(width);
let dotWidth = listRef.current.children[0].offsetWidth;
setVisibleCount(Math.floor(width / dotWidth));
},
);
_react.useEffect(() => resizeObserver?.disconnect(), [resizeObserver]);
let refs = (0, _index.useMergedRefs)(ref, resizeRef, listRef);
let firstVisibleDotIndex = _react.useMemo(
() =>
(0, _index.getBoundedValue)(
currentIndex - Math.ceil(visibleCount / 2) + 1,
0,
slideCount - visibleCount,
),
[currentIndex, slideCount, visibleCount],
);
let lastVisibleDotIndex = _react.useMemo(
() =>
(0, _index.getBoundedValue)(
currentIndex + Math.floor(visibleCount / 2),
visibleCount - 1,
slideCount - 1,
),
[currentIndex, slideCount, visibleCount],
);
let dots = _react.useMemo(
() =>
Array(slideCount)
.fill(null)
.map((_, index) => {
let isFirstSmallDot =
(index === firstVisibleDotIndex && 0 !== index) ||
(index === lastVisibleDotIndex && index !== slideCount - 1);
let isSecondSmallDot =
(index === firstVisibleDotIndex + 1 && 1 !== index) ||
(index === lastVisibleDotIndex - 1 && index !== slideCount - 2);
let isClipped =
index < firstVisibleDotIndex || index > lastVisibleDotIndex;
return _react.createElement(_CarouselDot.CarouselDot, {
key: index,
'aria-label': `Slide ${index + 1}`,
isActive: index === currentIndex,
onClick: () => handleSlideChange(index),
isSmall: isSecondSmallDot,
isSmaller: isFirstSmallDot || isClipped,
id: idPrefix && `${idPrefix}--dot-${index}`,
});
}),
[
slideCount,
firstVisibleDotIndex,
lastVisibleDotIndex,
currentIndex,
idPrefix,
handleSlideChange,
],
);
let motionOk = (0, _index.useMediaQuery)(
'(prefers-reduced-motion: no-preference)',
);
_react.useEffect(() => {
let firstDot = listRef.current?.children[firstVisibleDotIndex];
if (!listRef.current || !firstDot) return;
listRef.current.scrollTo({
left: firstDot.offsetLeft - listRef.current.offsetLeft,
behavior: motionOk && !justMounted.current ? 'smooth' : 'auto',
});
if (justMounted.current) justMounted.current = false;
}, [
currentIndex,
firstVisibleDotIndex,
motionOk,
slideCount,
visibleCount,
width,
]);
let handleKeyDown = (event) => {
if (event.altKey || event.ctrlKey || event.metaKey || event.shiftKey)
return;
let key = event.key;
if ('ArrowLeft' === key || 'ArrowRight' === key) event.preventDefault();
};
let handleKeyUp = (event) => {
switch (event.key) {
case 'ArrowLeft':
handleSlideChange((slideCount + currentIndex - 1) % slideCount);
break;
case 'ArrowRight':
handleSlideChange((slideCount + currentIndex + 1) % slideCount);
break;
}
};
return _react.createElement(
_react.Fragment,
null,
_react.createElement(
_index.Box,
{
className: (0, _classnames.default)(
'iui-carousel-navigation-dots',
className,
),
role: 'tablist',
'aria-label': 'Slides',
ref: refs,
onKeyDown: handleKeyDown,
onKeyUp: handleKeyUp,
tabIndex: -1,
...rest,
},
children ?? dots,
),
);
});
if ('development' === process.env.NODE_ENV)
CarouselDotsList.displayName = 'Carousel.DotsList';