@snack-uikit/carousel 0.2.21-preview-e5174ad1.0 → 0.2.22-preview-71543426.0
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/CHANGELOG.md +11 -0
- package/dist/cjs/components/Control/Control.js +1 -3
- package/dist/cjs/components/ItemProvider/ItemProvider.js +23 -8
- package/dist/esm/components/Control/Control.js +1 -3
- package/dist/esm/components/ItemProvider/ItemProvider.js +23 -12
- package/package.json +5 -5
- package/src/components/Control/Control.tsx +1 -3
- package/src/components/ItemProvider/ItemProvider.tsx +41 -13
- package/src/components/ItemProvider/styles.module.scss +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,17 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
## 0.2.21 (2024-10-17)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
### Bug Fixes
|
|
10
|
+
|
|
11
|
+
* **PDS-882:** scroll to partially visible slide on click ([f974fa2](https://github.com/cloud-ru-tech/snack-uikit/commit/f974fa298b3b972e4a27cb9cc5a065d92c583577))
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
6
17
|
## 0.2.20 (2024-09-23)
|
|
7
18
|
|
|
8
19
|
### Only dependencies have been changed
|
|
@@ -31,9 +31,7 @@ exports.Control = (0, react_1.forwardRef)((_a, ref) => {
|
|
|
31
31
|
return (0, jsx_runtime_1.jsx)("button", Object.assign({
|
|
32
32
|
ref: ref,
|
|
33
33
|
className: styles_module_scss_1.default.control,
|
|
34
|
-
onClick:
|
|
35
|
-
onClick === null || onClick === void 0 ? void 0 : onClick();
|
|
36
|
-
},
|
|
34
|
+
onClick: onClick,
|
|
37
35
|
type: 'button',
|
|
38
36
|
"data-variant": variant
|
|
39
37
|
}, (0, utils_1.extractSupportProps)(rest), {
|
|
@@ -58,28 +58,28 @@ function ItemProvider(_ref) {
|
|
|
58
58
|
return () => observer.disconnect();
|
|
59
59
|
}, [recalculateItemsSize]);
|
|
60
60
|
const itemsTrackerRef = (0, react_1.useRef)(null);
|
|
61
|
-
|
|
61
|
+
const hideNonVisibleItems = () => {
|
|
62
62
|
var _a;
|
|
63
|
-
(_a = itemsTrackerRef.current) === null || _a === void 0 ? void 0 : _a.querySelectorAll(`[data-test-id=${testIds_1.TEST_IDS.trackItem}]`).forEach(
|
|
63
|
+
(_a = itemsTrackerRef.current) === null || _a === void 0 ? void 0 : _a.querySelectorAll(`[data-test-id=${testIds_1.TEST_IDS.trackItem}]`).forEach(slide => {
|
|
64
64
|
slide.setAttribute('aria-hidden', '0');
|
|
65
|
-
slide.querySelectorAll('a, button, select, input, textarea, [tabindex="0"]').forEach(
|
|
65
|
+
slide.querySelectorAll('a, button, select, input, textarea, [tabindex="0"]').forEach(focusableElement => {
|
|
66
66
|
focusableElement.setAttribute('tabindex', '-5');
|
|
67
67
|
focusableElement.classList.add(styles_module_scss_1.default.hiddenItem);
|
|
68
68
|
});
|
|
69
69
|
});
|
|
70
|
-
}
|
|
71
|
-
|
|
70
|
+
};
|
|
71
|
+
const showVisibleItems = (slide, page, show) => {
|
|
72
72
|
var _a;
|
|
73
73
|
(_a = itemsTrackerRef.current) === null || _a === void 0 ? void 0 : _a.querySelectorAll(`[data-test-id=${testIds_1.TEST_IDS.trackItem}]`).forEach((item, i) => {
|
|
74
74
|
if (i >= page * slide && i < page * slide + Math.trunc(show)) {
|
|
75
75
|
item.removeAttribute('aria-hidden');
|
|
76
|
-
item.querySelectorAll('a, button, select, input, textarea, [tabindex="-5"]').forEach(
|
|
76
|
+
item.querySelectorAll('a, button, select, input, textarea, [tabindex="-5"]').forEach(focusableElement => {
|
|
77
77
|
focusableElement.setAttribute('tabindex', '0');
|
|
78
78
|
focusableElement.classList.remove(styles_module_scss_1.default.hiddenItem);
|
|
79
79
|
});
|
|
80
80
|
}
|
|
81
81
|
});
|
|
82
|
-
}
|
|
82
|
+
};
|
|
83
83
|
const transform = (0, react_1.useMemo)(() => Number(-(page * scrollBy * computedValues.itemWidth + computedValues.gap * page * scrollBy)), [computedValues.gap, computedValues.itemWidth, page, scrollBy]);
|
|
84
84
|
(0, react_1.useEffect)(() => {
|
|
85
85
|
hideNonVisibleItems();
|
|
@@ -147,11 +147,23 @@ function ItemProvider(_ref) {
|
|
|
147
147
|
onMouseUp: handleDragFinish,
|
|
148
148
|
onMouseMove: handleDragMove
|
|
149
149
|
} : {};
|
|
150
|
+
const handleSlideClick = (0, react_1.useCallback)(e => {
|
|
151
|
+
var _a, _b;
|
|
152
|
+
const slideRect = e.currentTarget.getBoundingClientRect();
|
|
153
|
+
const containerRect = (_a = containerRef.current) === null || _a === void 0 ? void 0 : _a.getBoundingClientRect();
|
|
154
|
+
const containerViewport = (_b = containerRect === null || containerRect === void 0 ? void 0 : containerRect.right) !== null && _b !== void 0 ? _b : 0;
|
|
155
|
+
const slidePositionDelta = containerViewport - slideRect.right;
|
|
156
|
+
const minPos = Math.min(slidePositionDelta, slideRect.x);
|
|
157
|
+
if (minPos < 0) {
|
|
158
|
+
slideCallback(slidePositionDelta);
|
|
159
|
+
}
|
|
160
|
+
}, [slideCallback]);
|
|
150
161
|
return (0, jsx_runtime_1.jsx)("div", {
|
|
151
162
|
ref: containerRef,
|
|
152
163
|
className: styles_module_scss_1.default.itemProvider,
|
|
153
164
|
"data-pointers": !drag.pointers || undefined,
|
|
154
165
|
"data-swipe": swipe || undefined,
|
|
166
|
+
"data-gap": gap,
|
|
155
167
|
style: Object.assign({}, Boolean(gap) ? {
|
|
156
168
|
'--gap': gap
|
|
157
169
|
} : {}),
|
|
@@ -163,13 +175,16 @@ function ItemProvider(_ref) {
|
|
|
163
175
|
transition: `transform ${transition}s ease 0s`
|
|
164
176
|
},
|
|
165
177
|
ref: itemsTrackerRef,
|
|
166
|
-
children: items.map((item, i) =>
|
|
178
|
+
children: items.map((item, i) =>
|
|
179
|
+
// eslint-disable-next-line jsx-a11y/no-noninteractive-element-interactions
|
|
180
|
+
(0, jsx_runtime_1.jsx)("div", {
|
|
167
181
|
style: {
|
|
168
182
|
width: computedValues.itemWidth
|
|
169
183
|
},
|
|
170
184
|
className: styles_module_scss_1.default.itemContainer,
|
|
171
185
|
role: 'group',
|
|
172
186
|
"data-test-id": testIds_1.TEST_IDS.trackItem,
|
|
187
|
+
onClick: handleSlideClick,
|
|
173
188
|
children: item
|
|
174
189
|
}, i))
|
|
175
190
|
}))
|
|
@@ -16,7 +16,5 @@ import { extractSupportProps } from '@snack-uikit/utils';
|
|
|
16
16
|
import styles from './styles.module.css';
|
|
17
17
|
export const Control = forwardRef((_a, ref) => {
|
|
18
18
|
var { onClick, variant } = _a, rest = __rest(_a, ["onClick", "variant"]);
|
|
19
|
-
return (_jsx("button", Object.assign({ ref: ref, className: styles.control, onClick: ()
|
|
20
|
-
onClick === null || onClick === void 0 ? void 0 : onClick();
|
|
21
|
-
}, type: 'button', "data-variant": variant }, extractSupportProps(rest), { children: _jsx(ChevronLeftSVG, { size: 24, className: styles.icon }) })));
|
|
19
|
+
return (_jsx("button", Object.assign({ ref: ref, className: styles.control, onClick: onClick, type: 'button', "data-variant": variant }, extractSupportProps(rest), { children: _jsx(ChevronLeftSVG, { size: 24, className: styles.icon }) })));
|
|
22
20
|
});
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import debounce from 'lodash.debounce';
|
|
3
|
-
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
3
|
+
import { useCallback, useEffect, useMemo, useRef, useState, } from 'react';
|
|
4
4
|
import { TEST_IDS } from '../../testIds';
|
|
5
5
|
import { getPageX } from './helpers';
|
|
6
6
|
import styles from './styles.module.css';
|
|
@@ -37,30 +37,28 @@ export function ItemProvider({ items, showItems, scrollBy, slideCallback, transi
|
|
|
37
37
|
return () => observer.disconnect();
|
|
38
38
|
}, [recalculateItemsSize]);
|
|
39
39
|
const itemsTrackerRef = useRef(null);
|
|
40
|
-
|
|
40
|
+
const hideNonVisibleItems = () => {
|
|
41
41
|
var _a;
|
|
42
|
-
(_a = itemsTrackerRef.current) === null || _a === void 0 ? void 0 : _a.querySelectorAll(`[data-test-id=${TEST_IDS.trackItem}]`).forEach(
|
|
42
|
+
(_a = itemsTrackerRef.current) === null || _a === void 0 ? void 0 : _a.querySelectorAll(`[data-test-id=${TEST_IDS.trackItem}]`).forEach(slide => {
|
|
43
43
|
slide.setAttribute('aria-hidden', '0');
|
|
44
|
-
slide.querySelectorAll('a, button, select, input, textarea, [tabindex="0"]').forEach(
|
|
44
|
+
slide.querySelectorAll('a, button, select, input, textarea, [tabindex="0"]').forEach(focusableElement => {
|
|
45
45
|
focusableElement.setAttribute('tabindex', '-5');
|
|
46
46
|
focusableElement.classList.add(styles.hiddenItem);
|
|
47
47
|
});
|
|
48
48
|
});
|
|
49
|
-
}
|
|
50
|
-
|
|
49
|
+
};
|
|
50
|
+
const showVisibleItems = (slide, page, show) => {
|
|
51
51
|
var _a;
|
|
52
52
|
(_a = itemsTrackerRef.current) === null || _a === void 0 ? void 0 : _a.querySelectorAll(`[data-test-id=${TEST_IDS.trackItem}]`).forEach((item, i) => {
|
|
53
53
|
if (i >= page * slide && i < page * slide + Math.trunc(show)) {
|
|
54
54
|
item.removeAttribute('aria-hidden');
|
|
55
|
-
item
|
|
56
|
-
.querySelectorAll('a, button, select, input, textarea, [tabindex="-5"]')
|
|
57
|
-
.forEach(function (focusableElement) {
|
|
55
|
+
item.querySelectorAll('a, button, select, input, textarea, [tabindex="-5"]').forEach(focusableElement => {
|
|
58
56
|
focusableElement.setAttribute('tabindex', '0');
|
|
59
57
|
focusableElement.classList.remove(styles.hiddenItem);
|
|
60
58
|
});
|
|
61
59
|
}
|
|
62
60
|
});
|
|
63
|
-
}
|
|
61
|
+
};
|
|
64
62
|
const transform = useMemo(() => Number(-(page * scrollBy * computedValues.itemWidth + computedValues.gap * page * scrollBy)), [computedValues.gap, computedValues.itemWidth, page, scrollBy]);
|
|
65
63
|
useEffect(() => {
|
|
66
64
|
hideNonVisibleItems();
|
|
@@ -117,8 +115,21 @@ export function ItemProvider({ items, showItems, scrollBy, slideCallback, transi
|
|
|
117
115
|
onMouseMove: handleDragMove,
|
|
118
116
|
}
|
|
119
117
|
: {};
|
|
120
|
-
|
|
118
|
+
const handleSlideClick = useCallback(e => {
|
|
119
|
+
var _a, _b;
|
|
120
|
+
const slideRect = e.currentTarget.getBoundingClientRect();
|
|
121
|
+
const containerRect = (_a = containerRef.current) === null || _a === void 0 ? void 0 : _a.getBoundingClientRect();
|
|
122
|
+
const containerViewport = (_b = containerRect === null || containerRect === void 0 ? void 0 : containerRect.right) !== null && _b !== void 0 ? _b : 0;
|
|
123
|
+
const slidePositionDelta = containerViewport - slideRect.right;
|
|
124
|
+
const minPos = Math.min(slidePositionDelta, slideRect.x);
|
|
125
|
+
if (minPos < 0) {
|
|
126
|
+
slideCallback(slidePositionDelta);
|
|
127
|
+
}
|
|
128
|
+
}, [slideCallback]);
|
|
129
|
+
return (_jsx("div", { ref: containerRef, className: styles.itemProvider, "data-pointers": !drag.pointers || undefined, "data-swipe": swipe || undefined, "data-gap": gap, style: Object.assign({}, (Boolean(gap) ? { '--gap': gap } : {})), children: _jsx("div", Object.assign({}, swipeProps, { className: styles.itemTracker, "data-test-id": TEST_IDS.trackLine, style: {
|
|
121
130
|
transform: `translateX(${transform - drag.drag}px)`,
|
|
122
131
|
transition: `transform ${transition}s ease 0s`,
|
|
123
|
-
}, ref: itemsTrackerRef, children: items.map((item, i) => (
|
|
132
|
+
}, ref: itemsTrackerRef, children: items.map((item, i) => (
|
|
133
|
+
// eslint-disable-next-line jsx-a11y/no-noninteractive-element-interactions
|
|
134
|
+
_jsx("div", { style: { width: computedValues.itemWidth }, className: styles.itemContainer, role: 'group', "data-test-id": TEST_IDS.trackItem, onClick: handleSlideClick, children: item }, i))) })) }));
|
|
124
135
|
}
|
package/package.json
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
7
|
-
"version": "0.2.
|
|
7
|
+
"version": "0.2.22-preview-71543426.0",
|
|
8
8
|
"sideEffects": [
|
|
9
9
|
"*.css",
|
|
10
10
|
"*.woff",
|
|
@@ -34,12 +34,12 @@
|
|
|
34
34
|
"license": "Apache-2.0",
|
|
35
35
|
"scripts": {},
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"@snack-uikit/icons": "0.22.2-preview-
|
|
38
|
-
"@snack-uikit/pagination": "0.7.2-preview-
|
|
39
|
-
"@snack-uikit/utils": "3.4.1-preview-
|
|
37
|
+
"@snack-uikit/icons": "0.22.2-preview-71543426.0",
|
|
38
|
+
"@snack-uikit/pagination": "0.7.2-preview-71543426.0",
|
|
39
|
+
"@snack-uikit/utils": "3.4.1-preview-71543426.0",
|
|
40
40
|
"classnames": "2.3.2",
|
|
41
41
|
"lodash.debounce": "4.0.8",
|
|
42
42
|
"uncontrollable": "8.0.4"
|
|
43
43
|
},
|
|
44
|
-
"gitHead": "
|
|
44
|
+
"gitHead": "3102614275e261c8f41db0f6c00a1f6b6276b2a9"
|
|
45
45
|
}
|
|
@@ -15,9 +15,7 @@ export const Control = forwardRef<HTMLButtonElement, ControlProps>(
|
|
|
15
15
|
<button
|
|
16
16
|
ref={ref}
|
|
17
17
|
className={styles.control}
|
|
18
|
-
onClick={
|
|
19
|
-
onClick?.();
|
|
20
|
-
}}
|
|
18
|
+
onClick={onClick}
|
|
21
19
|
type='button'
|
|
22
20
|
data-variant={variant}
|
|
23
21
|
{...extractSupportProps(rest)}
|
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
import debounce from 'lodash.debounce';
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
MouseEvent,
|
|
4
|
+
MouseEventHandler,
|
|
5
|
+
ReactElement,
|
|
6
|
+
TouchEvent,
|
|
7
|
+
useCallback,
|
|
8
|
+
useEffect,
|
|
9
|
+
useMemo,
|
|
10
|
+
useRef,
|
|
11
|
+
useState,
|
|
12
|
+
} from 'react';
|
|
3
13
|
|
|
4
14
|
import { TEST_IDS } from '../../testIds';
|
|
5
15
|
import { getPageX } from './helpers';
|
|
@@ -73,30 +83,28 @@ export function ItemProvider({
|
|
|
73
83
|
|
|
74
84
|
const itemsTrackerRef = useRef<HTMLDivElement>(null);
|
|
75
85
|
|
|
76
|
-
|
|
77
|
-
itemsTrackerRef.current?.querySelectorAll(`[data-test-id=${TEST_IDS.trackItem}]`).forEach(
|
|
86
|
+
const hideNonVisibleItems = () => {
|
|
87
|
+
itemsTrackerRef.current?.querySelectorAll(`[data-test-id=${TEST_IDS.trackItem}]`).forEach(slide => {
|
|
78
88
|
slide.setAttribute('aria-hidden', '0');
|
|
79
89
|
|
|
80
|
-
slide.querySelectorAll('a, button, select, input, textarea, [tabindex="0"]').forEach(
|
|
90
|
+
slide.querySelectorAll('a, button, select, input, textarea, [tabindex="0"]').forEach(focusableElement => {
|
|
81
91
|
focusableElement.setAttribute('tabindex', '-5');
|
|
82
92
|
focusableElement.classList.add(styles.hiddenItem);
|
|
83
93
|
});
|
|
84
94
|
});
|
|
85
|
-
}
|
|
95
|
+
};
|
|
86
96
|
|
|
87
|
-
|
|
97
|
+
const showVisibleItems = (slide: number, page: number, show: number) => {
|
|
88
98
|
itemsTrackerRef.current?.querySelectorAll(`[data-test-id=${TEST_IDS.trackItem}]`).forEach((item, i) => {
|
|
89
99
|
if (i >= page * slide && i < page * slide + Math.trunc(show)) {
|
|
90
100
|
item.removeAttribute('aria-hidden');
|
|
91
|
-
item
|
|
92
|
-
.
|
|
93
|
-
.
|
|
94
|
-
|
|
95
|
-
focusableElement.classList.remove(styles.hiddenItem);
|
|
96
|
-
});
|
|
101
|
+
item.querySelectorAll('a, button, select, input, textarea, [tabindex="-5"]').forEach(focusableElement => {
|
|
102
|
+
focusableElement.setAttribute('tabindex', '0');
|
|
103
|
+
focusableElement.classList.remove(styles.hiddenItem);
|
|
104
|
+
});
|
|
97
105
|
}
|
|
98
106
|
});
|
|
99
|
-
}
|
|
107
|
+
};
|
|
100
108
|
|
|
101
109
|
const transform = useMemo(
|
|
102
110
|
() => Number(-(page * scrollBy * computedValues.itemWidth + computedValues.gap * page * scrollBy)),
|
|
@@ -130,9 +138,11 @@ export function ItemProvider({
|
|
|
130
138
|
|
|
131
139
|
const handleDragFinish = (e: MouseEvent | TouchEvent) => {
|
|
132
140
|
e.persist();
|
|
141
|
+
|
|
133
142
|
if (drag.finished) {
|
|
134
143
|
return;
|
|
135
144
|
}
|
|
145
|
+
|
|
136
146
|
if (Math.abs(drag.drag) < swipeActivateLength) {
|
|
137
147
|
return setDrag({
|
|
138
148
|
initial: transform,
|
|
@@ -178,12 +188,28 @@ export function ItemProvider({
|
|
|
178
188
|
}
|
|
179
189
|
: {};
|
|
180
190
|
|
|
191
|
+
const handleSlideClick: MouseEventHandler = useCallback(
|
|
192
|
+
e => {
|
|
193
|
+
const slideRect = e.currentTarget.getBoundingClientRect();
|
|
194
|
+
const containerRect = containerRef.current?.getBoundingClientRect();
|
|
195
|
+
const containerViewport = containerRect?.right ?? 0;
|
|
196
|
+
const slidePositionDelta = containerViewport - slideRect.right;
|
|
197
|
+
const minPos = Math.min(slidePositionDelta, slideRect.x);
|
|
198
|
+
|
|
199
|
+
if (minPos < 0) {
|
|
200
|
+
slideCallback(slidePositionDelta);
|
|
201
|
+
}
|
|
202
|
+
},
|
|
203
|
+
[slideCallback],
|
|
204
|
+
);
|
|
205
|
+
|
|
181
206
|
return (
|
|
182
207
|
<div
|
|
183
208
|
ref={containerRef}
|
|
184
209
|
className={styles.itemProvider}
|
|
185
210
|
data-pointers={!drag.pointers || undefined}
|
|
186
211
|
data-swipe={swipe || undefined}
|
|
212
|
+
data-gap={gap}
|
|
187
213
|
style={{
|
|
188
214
|
...(Boolean(gap) ? { '--gap': gap } : {}),
|
|
189
215
|
}}
|
|
@@ -199,12 +225,14 @@ export function ItemProvider({
|
|
|
199
225
|
ref={itemsTrackerRef}
|
|
200
226
|
>
|
|
201
227
|
{items.map((item, i) => (
|
|
228
|
+
// eslint-disable-next-line jsx-a11y/no-noninteractive-element-interactions
|
|
202
229
|
<div
|
|
203
230
|
key={i}
|
|
204
231
|
style={{ width: computedValues.itemWidth }}
|
|
205
232
|
className={styles.itemContainer}
|
|
206
233
|
role='group'
|
|
207
234
|
data-test-id={TEST_IDS.trackItem}
|
|
235
|
+
onClick={handleSlideClick}
|
|
208
236
|
>
|
|
209
237
|
{item}
|
|
210
238
|
</div>
|