UNPKG

@gfazioli/mantine-picker

Version:

Picker component is a wrapper for any component that can be flipped. It is used to create cards, flip boxes and more.

897 lines (894 loc) 32 kB
'use client'; import React, { useRef, useState, useEffect, useCallback } from 'react'; import { createVarsResolver, polymorphicFactory, useProps, useStyles, Box, Text } from '@mantine/core'; import classes from './Picker.module.css.mjs'; const defaultProps = { animate: true, animationDuration: 300, loop: true, itemHeight: 40, visibleItems: 3, preventPageScroll: true, disabled: false, readOnly: false, minItemOpacity: 0.3, minItemScale: 0.85, maxBlurAmount: 0, easingFunction: "linear", focusable: true, wheelSensitivity: 1, withHighlight: true, withDividers: true, withMask: false, enable3D: true, perspective: 300, maxRotation: 60, cylinderRadius: 4, momentum: 0.95, decelerationRate: 0.95, maskHeight: 55, maskIntensity: 10, leftSectionWidth: "auto", rightSectionWidth: "auto", rotateY: 0 }; const varsResolver = createVarsResolver( (_, { itemHeight, animationDuration, visibleItems, easingFunction, perspective, maskHeight, maskIntensity, rotateY, enable3D }) => { const pickerHeight = (itemHeight || 40) * (visibleItems || 5); return { root: { "--picker-height": `${pickerHeight}px`, "--picker-item-height": `${itemHeight || 40}px`, "--picker-animation-duration": `${animationDuration || 300}ms`, "--picker-animation-easing": easingFunction || "ease-out", "--picker-perspective": `${perspective || 300}px`, "--picker-mask-height": `${maskHeight || 45}%`, "--picker-mask-intensity": `${maskIntensity || 60}%`, "--picker-rotate-y": enable3D ? `${rotateY || 0}deg` : "0deg" } }; } ); const Picker = polymorphicFactory((_props, ref) => { const props = useProps("Picker", defaultProps, _props); const { data, value, onChange, animate, animationDuration, easingFunction, loop, itemHeight, visibleItems, renderItem, preventPageScroll, disabled, readOnly, minItemOpacity, minItemScale, maxBlurAmount, id, label, description, keyboardHint, focusable, wheelSensitivity, withHighlight, withDividers, withMask, enable3D, perspective, maxRotation, cylinderRadius, momentum, decelerationRate, maskHeight, maskIntensity, leftSection, rightSection, leftSectionWidth, rightSectionWidth, rotateY, size, lineClamp, truncate, inline, inherit, gradient, fw, fs, td, c, tt, ta, variant, classNames, style, styles, unstyled, vars, className, ...others } = props; const textProps = { size, lineClamp, truncate, inline, inherit, gradient, fw, fs, td, c, tt, ta, variant }; const getStyles = useStyles({ name: "Picker", props, classes, className, style, classNames, styles, unstyled, vars, varsResolver }); const selectedIndex = value !== void 0 ? data.indexOf(value) : 0; const prevValueRef = useRef(value); const containerRef = useRef(null); const rootRef = useRef(null); const [isDragging, setIsDragging] = useState(false); const [lastY, setLastY] = useState(0); const [dragOffset, setDragOffset] = useState(0); const [velocity, setVelocity] = useState(0); const [isMomentumScrolling, setIsMomentumScrolling] = useState(false); const lastMoveTime = useRef(0); const lastMovePosition = useRef(0); const momentumAnimationRef = useRef(null); const [isWheeling, setIsWheeling] = useState(false); const wheelTimeoutRef = useRef(null); const lastWheelEventTime = useRef(0); const [currentPosition, setCurrentPosition] = useState(selectedIndex); const [isAnimating, setIsAnimating] = useState(false); const animationRef = useRef(null); const [isFocused, setIsFocused] = useState(false); const prevLoopRef = useRef(loop); useEffect(() => { if (value !== prevValueRef.current && selectedIndex !== -1) { if (animate) { const targetPosition = findBestPathToValue(selectedIndex); animateToPosition(targetPosition); } else { setCurrentPosition(selectedIndex); } prevValueRef.current = value; } }, [value, selectedIndex, animate]); useEffect(() => { if (prevLoopRef.current !== loop) { if (!loop) { const clampedPosition = Math.max(0, Math.min(data.length - 1, currentPosition)); if (clampedPosition !== currentPosition) { setCurrentPosition(clampedPosition); } if (animationRef.current !== null) { cancelAnimationFrame(animationRef.current); animationRef.current = null; setIsAnimating(false); } if (momentumAnimationRef.current !== null) { cancelAnimationFrame(momentumAnimationRef.current); momentumAnimationRef.current = null; setIsMomentumScrolling(false); } const realIndex = Math.round(clampedPosition); if (realIndex >= 0 && realIndex < data.length && value !== data[realIndex]) { onChange?.(data[realIndex]); } } setIsDragging(false); prevLoopRef.current = loop; } }, [loop, currentPosition, onChange, value, data]); const findBestPathToValue = (targetIndex) => { if (!loop || data.length <= 1) { return targetIndex; } if (data.length <= (visibleItems || 5)) { const currentRoundedPos2 = Math.round(currentPosition); const currentDataIndex2 = (currentRoundedPos2 % data.length + data.length) % data.length; let directPath2 = targetIndex - currentDataIndex2; if (directPath2 > data.length / 2) { directPath2 -= data.length; } else if (directPath2 < -data.length / 2) { directPath2 += data.length; } return currentRoundedPos2 + directPath2; } const currentRoundedPos = Math.round(currentPosition); const currentDataIndex = (currentRoundedPos % data.length + data.length) % data.length; const directPath = Math.abs(targetIndex - currentDataIndex); const wrapPath = data.length - directPath; if (wrapPath < directPath) { if (targetIndex > currentDataIndex) { return currentRoundedPos - wrapPath; } return currentRoundedPos + wrapPath; } if (targetIndex > currentDataIndex) { return currentRoundedPos + directPath; } return currentRoundedPos - directPath; }; const animateToPosition = (targetPosition) => { if (targetPosition === currentPosition || isAnimating) { return; } let clampedTargetPosition = targetPosition; if (!loop) { clampedTargetPosition = Math.max(0, Math.min(data.length - 1, targetPosition)); } if (animationRef.current !== null) { cancelAnimationFrame(animationRef.current); } if (momentumAnimationRef.current !== null) { cancelAnimationFrame(momentumAnimationRef.current); setIsMomentumScrolling(false); } setIsAnimating(true); const startTime = performance.now(); const startPosition = currentPosition; const distance = Math.abs(clampedTargetPosition - startPosition); const duration = Math.min( animationDuration || 300, Math.max(100, (animationDuration || 300) * Math.min(distance / 3, 1)) ); const animate2 = (time) => { const elapsed = time - startTime; const progress = Math.min(elapsed / duration, 1); const easeProgress = 1 - (1 - progress) * (1 - progress); const position = startPosition + (clampedTargetPosition - startPosition) * easeProgress; setCurrentPosition(position); if (progress < 1) { animationRef.current = requestAnimationFrame(animate2); } else { setIsAnimating(false); animationRef.current = null; setCurrentPosition(clampedTargetPosition); if (!disabled) { const realIndex2 = loop ? (Math.round(clampedTargetPosition) % data.length + data.length) % data.length : Math.round(clampedTargetPosition); onChange?.(data[realIndex2]); } const realIndex = loop ? (Math.round(clampedTargetPosition) % data.length + data.length) % data.length : Math.round(clampedTargetPosition); prevValueRef.current = data[realIndex]; } }; animationRef.current = requestAnimationFrame(animate2); }; const applyMomentum = () => { if (velocity === 0 || disabled) { return; } setIsMomentumScrolling(true); let currentVelocity = velocity * (momentum || 0.95); let currentPos = currentPosition; let lastDirection = Math.sign(currentVelocity); const momentumScroll = () => { currentVelocity *= decelerationRate || 0.95; let newPos = currentPos + currentVelocity; if (!loop) { const minPos = 0; const maxPos = data.length - 1; if (newPos < minPos) { newPos = minPos + (minPos - newPos) * 0.2; currentVelocity *= -0.5; } else if (newPos > maxPos) { newPos = maxPos - (newPos - maxPos) * 0.2; currentVelocity *= -0.5; } if (Math.abs(newPos - minPos) < 0.1) { newPos = minPos; } if (Math.abs(newPos - maxPos) < 0.1) { newPos = maxPos; } if (newPos === minPos || newPos === maxPos) { currentVelocity *= 0.7; } } currentPos = newPos; const currentDirection = Math.sign(currentVelocity); const directionChanged = lastDirection !== 0 && currentDirection !== 0 && lastDirection !== currentDirection; const isSlowEnough = Math.abs(currentVelocity) < 0.02; setCurrentPosition(currentPos); if (!isSlowEnough && !directionChanged) { momentumAnimationRef.current = requestAnimationFrame(momentumScroll); } else { setIsMomentumScrolling(false); let roundedPosition = Math.round(currentPos); if (!loop) { roundedPosition = Math.max(0, Math.min(data.length - 1, roundedPosition)); } setCurrentPosition(roundedPosition); requestAnimationFrame(() => { if (!disabled) { const realIndex2 = loop ? (roundedPosition % data.length + data.length) % data.length : roundedPosition; onChange?.(data[realIndex2]); } const realIndex = loop ? (roundedPosition % data.length + data.length) % data.length : roundedPosition; prevValueRef.current = data[realIndex]; }); } lastDirection = currentDirection; }; momentumAnimationRef.current = requestAnimationFrame(momentumScroll); }; useEffect(() => { return () => { if (animationRef.current !== null) { cancelAnimationFrame(animationRef.current); } if (momentumAnimationRef.current !== null) { cancelAnimationFrame(momentumAnimationRef.current); } if (wheelTimeoutRef.current) { clearTimeout(wheelTimeoutRef.current); } }; }, []); const handleMouseEnter = () => { const isInteractionDisabled = disabled || readOnly; if (preventPageScroll && !isInteractionDisabled && typeof document !== "undefined") { document.body.style.overflow = "hidden"; } }; const handleMouseLeave = () => { if (preventPageScroll && typeof document !== "undefined") { document.body.style.overflow = "auto"; } }; useEffect(() => { return () => { if (preventPageScroll && typeof document !== "undefined") { document.body.style.overflow = "auto"; } }; }, [preventPageScroll]); const halfVisible = Math.floor((visibleItems || 5) / 2); const handleMouseDown = (e) => { const isInteractionDisabled = disabled || readOnly; if (isAnimating || isInteractionDisabled || isMomentumScrolling) { return; } if (momentumAnimationRef.current !== null) { cancelAnimationFrame(momentumAnimationRef.current); setIsMomentumScrolling(false); } e.preventDefault(); setIsDragging(true); setLastY(e.clientY); setDragOffset(0); setVelocity(0); lastMoveTime.current = performance.now(); lastMovePosition.current = currentPosition; }; const handleTouchStart = (e) => { const isInteractionDisabled = disabled || readOnly; if (isAnimating || isInteractionDisabled || isMomentumScrolling) { return; } if (momentumAnimationRef.current !== null) { cancelAnimationFrame(momentumAnimationRef.current); setIsMomentumScrolling(false); } setIsDragging(true); setLastY(e.touches[0].clientY); setDragOffset(0); setVelocity(0); lastMoveTime.current = performance.now(); lastMovePosition.current = currentPosition; }; const clampPosition = (position) => { if (loop) { return position; } if (position < 0) { return position * 0.3; } else if (position > data.length - 1) { return data.length - 1 + (position - (data.length - 1)) * 0.3; } return position; }; const handleMouseMove = (e) => { const isInteractionDisabled = disabled || readOnly; if (!isDragging || isInteractionDisabled) { return; } const currentTime = performance.now(); const newY = e.clientY; const deltaY = newY - lastY; const timeDelta = currentTime - lastMoveTime.current; const itemOffsetRatio = deltaY / (itemHeight || 40); setCurrentPosition((prev) => { let newPosition = prev - itemOffsetRatio; newPosition = clampPosition(newPosition); if (timeDelta > 0) { const positionDelta = newPosition - lastMovePosition.current; setVelocity(positionDelta / timeDelta * 16); } lastMovePosition.current = newPosition; lastMoveTime.current = currentTime; return newPosition; }); setLastY(newY); }; const handleTouchMove = (e) => { const isInteractionDisabled = disabled || readOnly; if (!isDragging || isInteractionDisabled) { return; } const currentTime = performance.now(); const newY = e.touches[0].clientY; const deltaY = newY - lastY; const timeDelta = currentTime - lastMoveTime.current; const itemOffsetRatio = deltaY / (itemHeight || 40); setCurrentPosition((prev) => { let newPosition = prev - itemOffsetRatio; newPosition = clampPosition(newPosition); if (timeDelta > 0) { const positionDelta = newPosition - lastMovePosition.current; setVelocity(positionDelta / timeDelta * 16); } lastMovePosition.current = newPosition; lastMoveTime.current = currentTime; return newPosition; }); setLastY(newY); }; const handleMouseUp = () => { const isInteractionDisabled = disabled || readOnly; if (!isDragging || isInteractionDisabled) { return; } setIsDragging(false); setDragOffset(0); if (Math.abs(velocity) > 0.05) { applyMomentum(); } else { let roundedPosition = Math.round(currentPosition); if (!loop) { roundedPosition = Math.max(0, Math.min(data.length - 1, roundedPosition)); } if (roundedPosition !== currentPosition) { animateToPosition(roundedPosition); } else { if (!disabled) { const realIndex2 = loop ? (roundedPosition % data.length + data.length) % data.length : roundedPosition; onChange?.(data[realIndex2]); } const realIndex = loop ? (roundedPosition % data.length + data.length) % data.length : roundedPosition; prevValueRef.current = data[realIndex]; } } }; const handleTouchEnd = () => { const isInteractionDisabled = disabled || readOnly; if (!isDragging || isInteractionDisabled) { return; } setIsDragging(false); setDragOffset(0); if (Math.abs(velocity) > 0.05) { applyMomentum(); } else { let roundedPosition = Math.round(currentPosition); if (!loop) { roundedPosition = Math.max(0, Math.min(data.length - 1, roundedPosition)); } if (roundedPosition !== currentPosition) { animateToPosition(roundedPosition); } else { if (!disabled) { const realIndex2 = loop ? (roundedPosition % data.length + data.length) % data.length : roundedPosition; onChange?.(data[realIndex2]); } const realIndex = loop ? (roundedPosition % data.length + data.length) % data.length : roundedPosition; prevValueRef.current = data[realIndex]; } } }; useEffect(() => { const handleGlobalMouseMove = (e) => handleMouseMove(e); const handleGlobalMouseUp = () => handleMouseUp(); const handleGlobalTouchMove = (e) => handleTouchMove(e); const handleGlobalTouchEnd = () => handleTouchEnd(); if (isDragging) { window.addEventListener("mousemove", handleGlobalMouseMove, { passive: false }); window.addEventListener("mouseup", handleGlobalMouseUp); window.addEventListener("touchmove", handleGlobalTouchMove, { passive: false }); window.addEventListener("touchend", handleGlobalTouchEnd); } return () => { window.removeEventListener("mousemove", handleGlobalMouseMove); window.removeEventListener("mouseup", handleGlobalMouseUp); window.removeEventListener("touchmove", handleGlobalTouchMove); window.removeEventListener("touchend", handleGlobalTouchEnd); }; }, [isDragging, lastY, currentPosition, disabled, readOnly, loop, data.length]); const isWindows = useCallback(() => { if (typeof navigator !== "undefined") { return navigator.userAgent.indexOf("Windows") !== -1; } return false; }, []); const handleWheel = useCallback( (e) => { const isInteractionDisabled = disabled || readOnly; if (isAnimating || isInteractionDisabled || isMomentumScrolling) { return; } if (momentumAnimationRef.current !== null) { cancelAnimationFrame(momentumAnimationRef.current); setIsMomentumScrolling(false); } e.preventDefault(); e.stopPropagation(); setIsWheeling(true); let sensitivity = wheelSensitivity || 1; let delta = e.deltaY; if (e.deltaMode === 1) { delta *= 16; } else if (e.deltaMode === 2) { delta *= 100; } if (isWindows()) { sensitivity *= 0.2; } delta *= sensitivity; setCurrentPosition((prev) => { let newPosition = prev + delta / (itemHeight || 40) * 0.08; if (!loop) { if (newPosition < 0) { newPosition *= 0.3; } else if (newPosition > data.length - 1) { newPosition = data.length - 1 + (newPosition - (data.length - 1)) * 0.3; } } return newPosition; }); if (wheelTimeoutRef.current) { clearTimeout(wheelTimeoutRef.current); } lastWheelEventTime.current = Date.now(); wheelTimeoutRef.current = setTimeout(() => { if (Date.now() - lastWheelEventTime.current >= 150) { setIsWheeling(false); let roundedPosition = Math.round(currentPosition); if (!loop) { roundedPosition = Math.max(0, Math.min(data.length - 1, roundedPosition)); } if (roundedPosition !== currentPosition) { animateToPosition(roundedPosition); } else { if (!disabled) { const realIndex2 = loop ? (roundedPosition % data.length + data.length) % data.length : roundedPosition; onChange?.(data[realIndex2]); } const realIndex = loop ? (roundedPosition % data.length + data.length) % data.length : roundedPosition; prevValueRef.current = data[realIndex]; } wheelTimeoutRef.current = null; } else { if (wheelTimeoutRef.current) { clearTimeout(wheelTimeoutRef.current); } wheelTimeoutRef.current = setTimeout(() => { setIsWheeling(false); let roundedPosition = Math.round(currentPosition); if (!loop) { roundedPosition = Math.max(0, Math.min(data.length - 1, roundedPosition)); } if (roundedPosition !== currentPosition) { animateToPosition(roundedPosition); } else { if (!disabled) { const realIndex2 = loop ? (roundedPosition % data.length + data.length) % data.length : roundedPosition; onChange?.(data[realIndex2]); } const realIndex = loop ? (roundedPosition % data.length + data.length) % data.length : roundedPosition; prevValueRef.current = data[realIndex]; } wheelTimeoutRef.current = null; }, 150); } }, 150); }, [ currentPosition, data, loop, isAnimating, disabled, readOnly, itemHeight, onChange, wheelSensitivity, isMomentumScrolling, isWindows ] ); const handleKeyDown = useCallback( (e) => { const isInteractionDisabled = disabled || readOnly; if (isInteractionDisabled) { return; } if (momentumAnimationRef.current !== null) { cancelAnimationFrame(momentumAnimationRef.current); setIsMomentumScrolling(false); } switch (e.key) { case "ArrowUp": { e.preventDefault(); let prevPosition = Math.round(currentPosition) - 1; if (!loop) { prevPosition = Math.max(0, prevPosition); } animateToPosition(prevPosition); break; } case "ArrowDown": { e.preventDefault(); let nextPosition = Math.round(currentPosition) + 1; if (!loop) { nextPosition = Math.min(data.length - 1, nextPosition); } animateToPosition(nextPosition); break; } case "Home": e.preventDefault(); animateToPosition(0); break; case "End": e.preventDefault(); animateToPosition(data.length - 1); break; case "PageUp": { e.preventDefault(); let pageUpPosition = Math.round(currentPosition) - 5; if (loop) { pageUpPosition = (pageUpPosition % data.length + data.length) % data.length; } else { pageUpPosition = Math.max(0, pageUpPosition); } animateToPosition(pageUpPosition); break; } case "PageDown": { e.preventDefault(); let pageDownPosition = Math.round(currentPosition) + 5; if (loop) { pageDownPosition = (pageDownPosition % data.length + data.length) % data.length; } else { pageDownPosition = Math.min(data.length - 1, pageDownPosition); } animateToPosition(pageDownPosition); break; } } }, [currentPosition, data.length, loop, disabled, readOnly, isMomentumScrolling] ); const handleFocus = () => { if (!disabled) { setIsFocused(true); } }; const handleBlur = () => { setIsFocused(false); }; const handleItemClick = (clickedIndex, virtualIndex) => { const isInteractionDisabled = disabled || readOnly; if (isDragging || isAnimating || isInteractionDisabled || isMomentumScrolling) { return; } if (momentumAnimationRef.current !== null) { cancelAnimationFrame(momentumAnimationRef.current); setIsMomentumScrolling(false); } const currentRoundedPos = Math.round(currentPosition); const directVisualPath = virtualIndex - currentRoundedPos; animateToPosition(currentRoundedPos + directVisualPath); if (!disabled) { onChange?.(data[clickedIndex]); } prevValueRef.current = data[clickedIndex]; }; const createContinuousIndices = () => { if (!loop || data.length <= 1) { return Array.from({ length: data.length }, (_, i) => ({ dataIndex: i, virtualIndex: i })); } const duplicatesPerSide = Math.max( // At least visibleItems * 2 to ensure we have enough items on both sides (visibleItems || 5) * 2, // Or data.length * 2 to ensure we have enough duplicates for large datasets data.length * 2 ); const continuousIndices = []; const startIndex = Math.floor(currentPosition) - duplicatesPerSide; const endIndex = Math.floor(currentPosition) + duplicatesPerSide; for (let i = startIndex; i <= endIndex; i++) { const dataIndex = (i % data.length + data.length) % data.length; continuousIndices.push({ dataIndex, virtualIndex: i }); } return continuousIndices; }; const renderItems = () => { const items = []; const continuousIndices = createContinuousIndices(); const visibleRange = Math.max( halfVisible + 1, // Add just 1 extra item on each side for smoother scrolling Math.ceil(data.length / 2) // Keep this for small datasets ); for (const { dataIndex, virtualIndex } of continuousIndices) { const relativePos = virtualIndex - currentPosition; if (Math.abs(relativePos) <= visibleRange) { const itemOffset = relativePos * (itemHeight || 40) + dragOffset; const distanceFromCenter = Math.abs(relativePos); const maxDistance = halfVisible; const normalizedDistance = Math.min(distanceFromCenter / maxDistance, 1); const isSelected = Math.round(currentPosition) === virtualIndex; const minOpacity = typeof minItemOpacity === "number" ? minItemOpacity : 0.3; let opacity; if (isSelected) { opacity = 1; } else { opacity = minOpacity + (1 - minOpacity) * (1 - normalizedDistance); } const minScale = typeof minItemScale === "number" ? minItemScale : 0.85; const scale = isSelected ? 1 : minScale + (1 - minScale) * (1 - normalizedDistance); const blurAmount = maxBlurAmount && maxBlurAmount > 0 && !isSelected ? `${normalizedDistance * maxBlurAmount}px` : "0px"; const key = `item-${dataIndex}-${virtualIndex}`; let transform; if (enable3D) { const zTranslation = enable3D ? Math.abs(relativePos) * -20 : 0; const rotationAngle = enable3D ? -(relativePos * (maxRotation || 45)) / (cylinderRadius || 4) : 0; transform = ` translateY(${itemOffset}px) translateZ(${zTranslation}px) rotateX(${rotationAngle}deg) scale(${scale}) `; } else { transform = `translateY(${itemOffset}px) scale(${scale})`; } items.push( /* @__PURE__ */ React.createElement( Text, { ...textProps, span: true, key, id: id ? `${id}-item-${dataIndex}` : void 0, className: classes.item, role: "option", "aria-selected": isSelected || void 0, style: { transform, opacity, height: `${itemHeight || 40}px`, transition: isDragging || isWheeling || isMomentumScrolling ? "none" : void 0, filter: `blur(${blurAmount})`, // Add pointer-events: none when opacity is very low to prevent clicking on nearly invisible items // or when interaction is disabled pointerEvents: opacity < 0.1 || disabled || readOnly ? "none" : "auto", // For 3D effect backfaceVisibility: enable3D ? "hidden" : void 0, transformStyle: enable3D ? "preserve-3d" : void 0 }, "data-selected": isSelected || void 0, "data-dragging": isDragging || void 0, "data-wheeling": isWheeling || void 0, "data-animating": isAnimating || void 0, "data-momentum": isMomentumScrolling || void 0, "data-disabled": disabled || void 0, "data-readonly": readOnly || void 0, "data-3d": enable3D || void 0, onClick: () => handleItemClick(dataIndex, virtualIndex) }, renderItem ? renderItem(data[dataIndex]) : data[dataIndex] ) ); } } return items; }; const renderLeftSection = leftSection && /* @__PURE__ */ React.createElement("div", { className: classes.section, "data-position": "left", style: { width: leftSectionWidth } }, leftSection); const renderRightSection = rightSection && /* @__PURE__ */ React.createElement("div", { className: classes.section, "data-position": "right", style: { width: rightSectionWidth } }, rightSection); return /* @__PURE__ */ React.createElement( Box, { ref: (node) => { if (typeof ref === "function") { ref(node); } else if (ref) { ref.current = node; } rootRef.current = node; }, ...getStyles("root", { style: { perspective: enable3D ? `${perspective}px` : void 0 } }), ...others, onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave, "data-disabled": disabled || void 0, "data-readonly": readOnly || void 0, "data-focused": isFocused || void 0, "data-3d": enable3D || void 0, "data-with-left-section": !!leftSection || void 0, "data-with-right-section": !!rightSection || void 0, role: "group", "aria-labelledby": label && id ? `${id}-label` : void 0, "aria-describedby": (description && id ? `${id}-description` : void 0) || (keyboardHint && id ? `${id}-hint` : void 0) || void 0 }, label && id && /* @__PURE__ */ React.createElement("div", { id: `${id}-label`, className: "sr-only" }, label), description && id && /* @__PURE__ */ React.createElement("div", { id: `${id}-description`, className: "sr-only" }, description), keyboardHint && id && /* @__PURE__ */ React.createElement("div", { id: `${id}-hint`, className: "sr-only" }, keyboardHint), /* @__PURE__ */ React.createElement("div", { className: classes.pickerWrapper }, withHighlight && /* @__PURE__ */ React.createElement("div", { className: classes.highlight }), withMask && /* @__PURE__ */ React.createElement("div", { className: classes.mask }), withDividers && /* @__PURE__ */ React.createElement("div", { className: classes.dividers }), renderLeftSection, renderRightSection, /* @__PURE__ */ React.createElement( "div", { ref: containerRef, className: classes.container, onMouseDown: disabled || readOnly ? void 0 : handleMouseDown, onTouchStart: disabled || readOnly ? void 0 : handleTouchStart, onWheel: disabled || readOnly ? void 0 : handleWheel, onKeyDown: disabled || readOnly ? void 0 : handleKeyDown, onFocus: handleFocus, onBlur: handleBlur, tabIndex: disabled || readOnly ? -1 : 0, role: "listbox", "aria-activedescendant": id ? `${id}-item-${Math.round(currentPosition)}` : void 0, "aria-disabled": disabled || void 0, "aria-readonly": readOnly || void 0, style: { cursor: disabled ? "not-allowed" : readOnly ? "default" : isDragging ? "grabbing" : "grab", perspective: enable3D ? `${perspective}px` : void 0, transformStyle: enable3D ? "preserve-3d" : void 0 }, "data-animating": isAnimating || void 0, "data-wheeling": isWheeling || void 0, "data-momentum": isMomentumScrolling || void 0, "data-disabled": disabled || void 0, "data-readonly": readOnly || void 0, "data-3d": enable3D || void 0, "data-dragging": isDragging || void 0 }, renderItems() )) ); }); Picker.classes = classes; Picker.displayName = "Picker"; export { Picker }; //# sourceMappingURL=Picker.mjs.map