@pushwoosh/dumb-components 2.9.15 → 2.9.16

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pushwoosh/dumb-components",
3
- "version": "2.9.15",
3
+ "version": "2.9.16",
4
4
  "description": "React components to build Pushwoosh products",
5
5
  "main": "index.js",
6
6
  "module": "index.js",
@@ -5,6 +5,7 @@ import { CreateItemLabel, Dropdown, DropdownEmpty, DropdownItem, DropdownLoading
5
5
  import { Spinner } from '../../Spinner';
6
6
  const LOAD_MORE_THRESHOLD = 24;
7
7
  const CREATE_KEY = '__create__';
8
+ const TOUCH_SCROLL_THRESHOLD = 8;
8
9
  /**
9
10
  * Internal floating option list shared by the Combobox family: renders the rows,
10
11
  * empty/loading text, an optional "create" row and load-more support.
@@ -34,10 +35,44 @@ export function SuggestionsDropdown({
34
35
  const activeItem = items.find(item => item.active);
35
36
  const activeKey = createActive ? CREATE_KEY : activeItem?.key ?? null;
36
37
  useEffect(() => {
37
- if (activeKey === null) return;
38
- activeItemRef.current?.scrollIntoView({
38
+ if (activeKey === null) return undefined;
39
+ const scrollToActive = () => activeItemRef.current?.scrollIntoView({
39
40
  block: 'nearest'
40
41
  });
42
+ scrollToActive();
43
+ const list = activeItemRef.current?.parentElement;
44
+ if (!list || typeof ResizeObserver === 'undefined') return undefined;
45
+ const observer = new ResizeObserver(scrollToActive);
46
+ const stopFollowing = () => observer.disconnect();
47
+ const onScrollbarPointerDown = event => {
48
+ if (event.target === list) stopFollowing();
49
+ };
50
+ let touchStartY = null;
51
+ const onTouchStart = event => {
52
+ touchStartY = event.touches[0]?.clientY ?? null;
53
+ };
54
+ const onTouchMove = event => {
55
+ const y = event.touches[0]?.clientY;
56
+ if (touchStartY !== null && y !== undefined && Math.abs(y - touchStartY) > TOUCH_SCROLL_THRESHOLD) stopFollowing();
57
+ };
58
+ observer.observe(list);
59
+ list.addEventListener('wheel', stopFollowing, {
60
+ passive: true
61
+ });
62
+ list.addEventListener('touchstart', onTouchStart, {
63
+ passive: true
64
+ });
65
+ list.addEventListener('touchmove', onTouchMove, {
66
+ passive: true
67
+ });
68
+ list.addEventListener('pointerdown', onScrollbarPointerDown);
69
+ return () => {
70
+ observer.disconnect();
71
+ list.removeEventListener('wheel', stopFollowing);
72
+ list.removeEventListener('touchstart', onTouchStart);
73
+ list.removeEventListener('touchmove', onTouchMove);
74
+ list.removeEventListener('pointerdown', onScrollbarPointerDown);
75
+ };
41
76
  }, [activeKey]);
42
77
  if (typeof document === 'undefined') return null;
43
78
  const isEmpty = !loading && items.length === 0 && !createLabel;