@lumx/react 4.0.1-alpha.0 → 4.0.1-alpha.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.js +75 -17
- package/index.js.map +1 -1
- package/package.json +3 -3
package/index.js
CHANGED
|
@@ -43,7 +43,6 @@ import range from 'lodash/range';
|
|
|
43
43
|
import { mdiPlayCircleOutline } from '@lumx/icons/esm/play-circle-outline';
|
|
44
44
|
import { mdiPauseCircleOutline } from '@lumx/icons/esm/pause-circle-outline';
|
|
45
45
|
import chunk from 'lodash/chunk';
|
|
46
|
-
import debounce$1 from 'lodash/debounce';
|
|
47
46
|
import ReactDOM from 'react-dom';
|
|
48
47
|
import take from 'lodash/take';
|
|
49
48
|
import isObject from 'lodash/isObject';
|
|
@@ -11565,9 +11564,43 @@ const SlideshowControls = Object.assign(InternalSlideshowControls, {
|
|
|
11565
11564
|
useSlideshowControlsDefaultOptions: DEFAULT_OPTIONS
|
|
11566
11565
|
});
|
|
11567
11566
|
|
|
11567
|
+
/**
|
|
11568
|
+
* Polyfill-like helper for the scrollend event.
|
|
11569
|
+
* Uses native scrollend if available, otherwise falls back to a timeout.
|
|
11570
|
+
*
|
|
11571
|
+
* @param element The element to listen to.
|
|
11572
|
+
* @param callback The callback to execute when scrolling ends.
|
|
11573
|
+
* @param options Options for the listener (timeout and AbortSignal).
|
|
11574
|
+
*/
|
|
11575
|
+
function onScrollEnd(element, callback, options = {}) {
|
|
11576
|
+
const {
|
|
11577
|
+
timeout = 150,
|
|
11578
|
+
signal
|
|
11579
|
+
} = options;
|
|
11580
|
+
|
|
11581
|
+
// Native scrollend
|
|
11582
|
+
if ('onscrollend' in window) {
|
|
11583
|
+
element.addEventListener('scrollend', callback, {
|
|
11584
|
+
signal
|
|
11585
|
+
});
|
|
11586
|
+
return;
|
|
11587
|
+
}
|
|
11588
|
+
|
|
11589
|
+
// Fallback for browsers that don't support scrollend
|
|
11590
|
+
let timer;
|
|
11591
|
+
const handleScroll = () => {
|
|
11592
|
+
clearTimeout(timer);
|
|
11593
|
+
timer = setTimeout(callback, timeout);
|
|
11594
|
+
};
|
|
11595
|
+
element.addEventListener('scroll', handleScroll, {
|
|
11596
|
+
signal
|
|
11597
|
+
});
|
|
11598
|
+
signal?.addEventListener('abort', () => clearTimeout(timer));
|
|
11599
|
+
}
|
|
11600
|
+
|
|
11568
11601
|
/**
|
|
11569
11602
|
* Hook to handle scroll synchronization for the Slideshow component.
|
|
11570
|
-
* It syncs the scroll position with the active index and vice
|
|
11603
|
+
* It syncs the scroll position with the active index and vice versa.
|
|
11571
11604
|
*/
|
|
11572
11605
|
const useSlideScroll = ({
|
|
11573
11606
|
enabled,
|
|
@@ -11576,43 +11609,68 @@ const useSlideScroll = ({
|
|
|
11576
11609
|
onChange
|
|
11577
11610
|
}) => {
|
|
11578
11611
|
const isAutoScrollRef = React__default.useRef(false);
|
|
11612
|
+
const isFromScrollRef = React__default.useRef(false);
|
|
11579
11613
|
|
|
11580
11614
|
// Sync State -> DOM (Programmatic Navigation)
|
|
11581
11615
|
React__default.useEffect(() => {
|
|
11582
|
-
if (!enabled || !wrapperRef.current) return;
|
|
11583
11616
|
const wrapper = wrapperRef.current;
|
|
11617
|
+
if (!enabled || !wrapper) {
|
|
11618
|
+
return;
|
|
11619
|
+
}
|
|
11620
|
+
|
|
11621
|
+
// Skip if currently scrolling
|
|
11622
|
+
if (isFromScrollRef.current) {
|
|
11623
|
+
return;
|
|
11624
|
+
}
|
|
11584
11625
|
const targetElement = wrapper.children[activeIndex];
|
|
11585
11626
|
if (!targetElement) return;
|
|
11627
|
+
let newScrollLeft = targetElement.offsetLeft;
|
|
11628
|
+
if (targetElement.offsetParent !== wrapper) {
|
|
11629
|
+
newScrollLeft -= wrapper.offsetLeft + wrapper.clientLeft;
|
|
11630
|
+
}
|
|
11631
|
+
if (Math.abs(wrapper.scrollLeft - newScrollLeft) < 1) {
|
|
11632
|
+
return;
|
|
11633
|
+
}
|
|
11586
11634
|
isAutoScrollRef.current = true;
|
|
11587
11635
|
wrapper.scrollTo({
|
|
11588
|
-
left:
|
|
11636
|
+
left: newScrollLeft,
|
|
11589
11637
|
behavior: !isReducedMotion() ? 'smooth' : undefined
|
|
11590
11638
|
});
|
|
11591
11639
|
}, [activeIndex, enabled, wrapperRef]);
|
|
11592
11640
|
|
|
11593
11641
|
// Sync DOM -> State (User Interaction)
|
|
11594
11642
|
React__default.useEffect(() => {
|
|
11595
|
-
if (!enabled || !wrapperRef.current) return undefined;
|
|
11596
11643
|
const wrapper = wrapperRef.current;
|
|
11597
|
-
|
|
11644
|
+
if (!enabled || !wrapper) return undefined;
|
|
11645
|
+
const controller = new AbortController();
|
|
11646
|
+
const {
|
|
11647
|
+
signal
|
|
11648
|
+
} = controller;
|
|
11649
|
+
const handleScroll = () => {
|
|
11650
|
+
// Skip if currently scrolling programmatically
|
|
11651
|
+
if (isAutoScrollRef.current) {
|
|
11652
|
+
return;
|
|
11653
|
+
}
|
|
11598
11654
|
const {
|
|
11599
11655
|
scrollLeft,
|
|
11600
11656
|
clientWidth
|
|
11601
11657
|
} = wrapper;
|
|
11602
11658
|
const newIndex = Math.round(scrollLeft / clientWidth);
|
|
11603
|
-
|
|
11604
|
-
|
|
11605
|
-
|
|
11606
|
-
|
|
11607
|
-
}
|
|
11659
|
+
isFromScrollRef.current = true;
|
|
11660
|
+
onChange?.(newIndex);
|
|
11661
|
+
};
|
|
11662
|
+
const reset = () => {
|
|
11608
11663
|
isAutoScrollRef.current = false;
|
|
11609
|
-
|
|
11610
|
-
wrapper.addEventListener('scroll', handleScroll);
|
|
11611
|
-
return () => {
|
|
11612
|
-
wrapper.removeEventListener('scroll', handleScroll);
|
|
11613
|
-
handleScroll.cancel();
|
|
11664
|
+
isFromScrollRef.current = false;
|
|
11614
11665
|
};
|
|
11615
|
-
|
|
11666
|
+
wrapper.addEventListener('scroll', handleScroll, {
|
|
11667
|
+
signal
|
|
11668
|
+
});
|
|
11669
|
+
onScrollEnd(wrapper, reset, {
|
|
11670
|
+
signal
|
|
11671
|
+
});
|
|
11672
|
+
return () => controller.abort();
|
|
11673
|
+
}, [enabled, onChange, wrapperRef]);
|
|
11616
11674
|
};
|
|
11617
11675
|
|
|
11618
11676
|
/**
|