@doyourjob/gravity-ui-page-constructor 5.31.245 → 5.31.246
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/build/cjs/blocks/LogoRotator/LogoRotator.js +36 -10
- package/build/cjs/blocks/LogoRotator/schema.d.ts +6 -0
- package/build/cjs/blocks/LogoRotator/schema.js +4 -0
- package/build/cjs/models/constructor-items/blocks.d.ts +2 -0
- package/build/esm/blocks/LogoRotator/LogoRotator.js +36 -10
- package/build/esm/blocks/LogoRotator/schema.d.ts +6 -0
- package/build/esm/blocks/LogoRotator/schema.js +4 -0
- package/build/esm/models/constructor-items/blocks.d.ts +2 -0
- package/package.json +1 -1
- package/schema/index.js +1 -1
- package/server/models/constructor-items/blocks.d.ts +2 -0
- package/widget/index.js +1 -1
|
@@ -10,8 +10,18 @@ const grid_1 = require("../../grid");
|
|
|
10
10
|
const utils_1 = require("../../utils");
|
|
11
11
|
const Item_1 = tslib_1.__importDefault(require("./Item"));
|
|
12
12
|
const b = (0, utils_1.block)('logo-rotator-block');
|
|
13
|
+
const DEFAULT_MIN_ROTATE_COUNT = 2;
|
|
14
|
+
const DEFAULT_MAX_ROTATE_COUNT = 4;
|
|
15
|
+
const pickRandomSlots = (slotIndices, count) => {
|
|
16
|
+
const shuffled = [...slotIndices];
|
|
17
|
+
for (let i = shuffled.length - 1; i > 0; i--) {
|
|
18
|
+
const j = Math.floor(Math.random() * (i + 1));
|
|
19
|
+
[shuffled[i], shuffled[j]] = [shuffled[j], shuffled[i]];
|
|
20
|
+
}
|
|
21
|
+
return shuffled.slice(0, count);
|
|
22
|
+
};
|
|
13
23
|
const LogoRotatorBlock = (props) => {
|
|
14
|
-
const { animated, title, theme, items, count, colSizes, rowMode } = props;
|
|
24
|
+
const { animated, title, theme, items, count, minRotateCount = DEFAULT_MIN_ROTATE_COUNT, maxRotateCount = DEFAULT_MAX_ROTATE_COUNT, colSizes, rowMode, } = props;
|
|
15
25
|
// Индексы логотипов, которые участвуют в ротации (не статичные)
|
|
16
26
|
const rotatableIndices = (0, react_1.useMemo)(() => items.map((item, i) => (item.isStatic ? -1 : i)).filter((i) => i !== -1), [items]);
|
|
17
27
|
// Инициализация слотов: статичные вставляются в начало, остальные по порядку
|
|
@@ -37,6 +47,7 @@ const LogoRotatorBlock = (props) => {
|
|
|
37
47
|
});
|
|
38
48
|
const [hidden, setHidden] = (0, react_1.useState)(() => Array(count).fill(false));
|
|
39
49
|
const nextIndexRef = (0, react_1.useRef)(count - 1);
|
|
50
|
+
const isHoveredRef = (0, react_1.useRef)(false);
|
|
40
51
|
// Держим актуальные slots в ref, чтобы не пересоздавать интервал при каждом изменении
|
|
41
52
|
const slotsRef = (0, react_1.useRef)(slots);
|
|
42
53
|
(0, react_1.useEffect)(() => {
|
|
@@ -45,33 +56,44 @@ const LogoRotatorBlock = (props) => {
|
|
|
45
56
|
(0, react_1.useEffect)(() => {
|
|
46
57
|
let timeout = null;
|
|
47
58
|
const interval = setInterval(() => {
|
|
59
|
+
if (isHoveredRef.current)
|
|
60
|
+
return;
|
|
48
61
|
// Выбираем только не-статичные слоты для замены
|
|
49
62
|
const rotatableSlotIndices = slotsRef.current
|
|
50
63
|
.map((itemIdx, slotIdx) => { var _a; return (((_a = items[itemIdx]) === null || _a === void 0 ? void 0 : _a.isStatic) ? -1 : slotIdx); })
|
|
51
64
|
.filter((i) => i !== -1);
|
|
52
65
|
if (rotatableSlotIndices.length === 0)
|
|
53
66
|
return;
|
|
54
|
-
const
|
|
67
|
+
const rotateMin = Math.min(minRotateCount, maxRotateCount);
|
|
68
|
+
const rotateMax = Math.max(minRotateCount, maxRotateCount);
|
|
69
|
+
const rotateCount = rotateMin + Math.floor(Math.random() * (rotateMax - rotateMin + 1));
|
|
70
|
+
const slotIndices = pickRandomSlots(rotatableSlotIndices, Math.min(rotateCount, rotatableSlotIndices.length));
|
|
55
71
|
setHidden((prev) => {
|
|
56
72
|
const next = [...prev];
|
|
57
|
-
|
|
73
|
+
slotIndices.forEach((slotIndex) => {
|
|
74
|
+
next[slotIndex] = true;
|
|
75
|
+
});
|
|
58
76
|
return next;
|
|
59
77
|
});
|
|
60
78
|
timeout = setTimeout(() => {
|
|
61
79
|
setSlots((prevSlots) => {
|
|
62
80
|
const newSlots = [...prevSlots];
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
81
|
+
let available = rotatableIndices.filter((i) => !newSlots.includes(i));
|
|
82
|
+
slotIndices.forEach((slotIndex) => {
|
|
83
|
+
if (available.length === 0)
|
|
84
|
+
return;
|
|
66
85
|
const newValue = available[nextIndexRef.current % available.length];
|
|
67
86
|
nextIndexRef.current++;
|
|
68
87
|
newSlots[slotIndex] = newValue;
|
|
69
|
-
|
|
88
|
+
available = available.filter((i) => i !== newValue);
|
|
89
|
+
});
|
|
70
90
|
return newSlots;
|
|
71
91
|
});
|
|
72
92
|
setHidden((prev) => {
|
|
73
93
|
const next = [...prev];
|
|
74
|
-
|
|
94
|
+
slotIndices.forEach((slotIndex) => {
|
|
95
|
+
next[slotIndex] = false;
|
|
96
|
+
});
|
|
75
97
|
return next;
|
|
76
98
|
});
|
|
77
99
|
}, 500);
|
|
@@ -82,14 +104,18 @@ const LogoRotatorBlock = (props) => {
|
|
|
82
104
|
clearTimeout(timeout);
|
|
83
105
|
}
|
|
84
106
|
};
|
|
85
|
-
}, [count, items, rotatableIndices]);
|
|
107
|
+
}, [count, items, maxRotateCount, minRotateCount, rotatableIndices]);
|
|
86
108
|
const renderItems = (0, react_1.useMemo)(() => slots.map((slot, index) => (react_1.default.createElement(Item_1.default, { key: index, colSizes: colSizes, url: items[slot].url, src: items[slot].src, hidden: hidden[index] }))), [colSizes, hidden, items, slots]);
|
|
87
109
|
const titleProps = !title || typeof title === 'string'
|
|
88
110
|
? { text: title, textSize: 'l' }
|
|
89
111
|
: title;
|
|
90
112
|
const hasTitle = Boolean(title);
|
|
91
113
|
return (react_1.default.createElement(AnimateBlock_1.default, { className: b({ theme }), animate: animated },
|
|
92
|
-
react_1.default.createElement("div", { className: b('root')
|
|
114
|
+
react_1.default.createElement("div", { className: b('root'), onMouseEnter: () => {
|
|
115
|
+
isHoveredRef.current = true;
|
|
116
|
+
}, onMouseLeave: () => {
|
|
117
|
+
isHoveredRef.current = false;
|
|
118
|
+
} },
|
|
93
119
|
hasTitle && (react_1.default.createElement(components_1.Title, { title: titleProps, className: b('title'), colSizes: { all: 12 } })),
|
|
94
120
|
rowMode ? (react_1.default.createElement("div", { className: b('row-items') }, slots.map((slot, index) => {
|
|
95
121
|
const item = items[slot];
|
|
@@ -303,6 +303,8 @@ export interface LogoRotatorBlockProps extends Animatable {
|
|
|
303
303
|
isStatic?: boolean;
|
|
304
304
|
}[];
|
|
305
305
|
count: number;
|
|
306
|
+
minRotateCount?: number;
|
|
307
|
+
maxRotateCount?: number;
|
|
306
308
|
colSizes?: Partial<Record<GridColumnSize, number>>;
|
|
307
309
|
theme?: TextTheme;
|
|
308
310
|
rowMode?: boolean;
|
|
@@ -7,8 +7,18 @@ import { block } from '../../utils';
|
|
|
7
7
|
import Item from './Item';
|
|
8
8
|
import './LogoRotator.css';
|
|
9
9
|
const b = block('logo-rotator-block');
|
|
10
|
+
const DEFAULT_MIN_ROTATE_COUNT = 2;
|
|
11
|
+
const DEFAULT_MAX_ROTATE_COUNT = 4;
|
|
12
|
+
const pickRandomSlots = (slotIndices, count) => {
|
|
13
|
+
const shuffled = [...slotIndices];
|
|
14
|
+
for (let i = shuffled.length - 1; i > 0; i--) {
|
|
15
|
+
const j = Math.floor(Math.random() * (i + 1));
|
|
16
|
+
[shuffled[i], shuffled[j]] = [shuffled[j], shuffled[i]];
|
|
17
|
+
}
|
|
18
|
+
return shuffled.slice(0, count);
|
|
19
|
+
};
|
|
10
20
|
export const LogoRotatorBlock = (props) => {
|
|
11
|
-
const { animated, title, theme, items, count, colSizes, rowMode } = props;
|
|
21
|
+
const { animated, title, theme, items, count, minRotateCount = DEFAULT_MIN_ROTATE_COUNT, maxRotateCount = DEFAULT_MAX_ROTATE_COUNT, colSizes, rowMode, } = props;
|
|
12
22
|
// Индексы логотипов, которые участвуют в ротации (не статичные)
|
|
13
23
|
const rotatableIndices = useMemo(() => items.map((item, i) => (item.isStatic ? -1 : i)).filter((i) => i !== -1), [items]);
|
|
14
24
|
// Инициализация слотов: статичные вставляются в начало, остальные по порядку
|
|
@@ -34,6 +44,7 @@ export const LogoRotatorBlock = (props) => {
|
|
|
34
44
|
});
|
|
35
45
|
const [hidden, setHidden] = useState(() => Array(count).fill(false));
|
|
36
46
|
const nextIndexRef = useRef(count - 1);
|
|
47
|
+
const isHoveredRef = useRef(false);
|
|
37
48
|
// Держим актуальные slots в ref, чтобы не пересоздавать интервал при каждом изменении
|
|
38
49
|
const slotsRef = useRef(slots);
|
|
39
50
|
useEffect(() => {
|
|
@@ -42,33 +53,44 @@ export const LogoRotatorBlock = (props) => {
|
|
|
42
53
|
useEffect(() => {
|
|
43
54
|
let timeout = null;
|
|
44
55
|
const interval = setInterval(() => {
|
|
56
|
+
if (isHoveredRef.current)
|
|
57
|
+
return;
|
|
45
58
|
// Выбираем только не-статичные слоты для замены
|
|
46
59
|
const rotatableSlotIndices = slotsRef.current
|
|
47
60
|
.map((itemIdx, slotIdx) => { var _a; return (((_a = items[itemIdx]) === null || _a === void 0 ? void 0 : _a.isStatic) ? -1 : slotIdx); })
|
|
48
61
|
.filter((i) => i !== -1);
|
|
49
62
|
if (rotatableSlotIndices.length === 0)
|
|
50
63
|
return;
|
|
51
|
-
const
|
|
64
|
+
const rotateMin = Math.min(minRotateCount, maxRotateCount);
|
|
65
|
+
const rotateMax = Math.max(minRotateCount, maxRotateCount);
|
|
66
|
+
const rotateCount = rotateMin + Math.floor(Math.random() * (rotateMax - rotateMin + 1));
|
|
67
|
+
const slotIndices = pickRandomSlots(rotatableSlotIndices, Math.min(rotateCount, rotatableSlotIndices.length));
|
|
52
68
|
setHidden((prev) => {
|
|
53
69
|
const next = [...prev];
|
|
54
|
-
|
|
70
|
+
slotIndices.forEach((slotIndex) => {
|
|
71
|
+
next[slotIndex] = true;
|
|
72
|
+
});
|
|
55
73
|
return next;
|
|
56
74
|
});
|
|
57
75
|
timeout = setTimeout(() => {
|
|
58
76
|
setSlots((prevSlots) => {
|
|
59
77
|
const newSlots = [...prevSlots];
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
78
|
+
let available = rotatableIndices.filter((i) => !newSlots.includes(i));
|
|
79
|
+
slotIndices.forEach((slotIndex) => {
|
|
80
|
+
if (available.length === 0)
|
|
81
|
+
return;
|
|
63
82
|
const newValue = available[nextIndexRef.current % available.length];
|
|
64
83
|
nextIndexRef.current++;
|
|
65
84
|
newSlots[slotIndex] = newValue;
|
|
66
|
-
|
|
85
|
+
available = available.filter((i) => i !== newValue);
|
|
86
|
+
});
|
|
67
87
|
return newSlots;
|
|
68
88
|
});
|
|
69
89
|
setHidden((prev) => {
|
|
70
90
|
const next = [...prev];
|
|
71
|
-
|
|
91
|
+
slotIndices.forEach((slotIndex) => {
|
|
92
|
+
next[slotIndex] = false;
|
|
93
|
+
});
|
|
72
94
|
return next;
|
|
73
95
|
});
|
|
74
96
|
}, 500);
|
|
@@ -79,14 +101,18 @@ export const LogoRotatorBlock = (props) => {
|
|
|
79
101
|
clearTimeout(timeout);
|
|
80
102
|
}
|
|
81
103
|
};
|
|
82
|
-
}, [count, items, rotatableIndices]);
|
|
104
|
+
}, [count, items, maxRotateCount, minRotateCount, rotatableIndices]);
|
|
83
105
|
const renderItems = useMemo(() => slots.map((slot, index) => (React.createElement(Item, { key: index, colSizes: colSizes, url: items[slot].url, src: items[slot].src, hidden: hidden[index] }))), [colSizes, hidden, items, slots]);
|
|
84
106
|
const titleProps = !title || typeof title === 'string'
|
|
85
107
|
? { text: title, textSize: 'l' }
|
|
86
108
|
: title;
|
|
87
109
|
const hasTitle = Boolean(title);
|
|
88
110
|
return (React.createElement(AnimateBlock, { className: b({ theme }), animate: animated },
|
|
89
|
-
React.createElement("div", { className: b('root')
|
|
111
|
+
React.createElement("div", { className: b('root'), onMouseEnter: () => {
|
|
112
|
+
isHoveredRef.current = true;
|
|
113
|
+
}, onMouseLeave: () => {
|
|
114
|
+
isHoveredRef.current = false;
|
|
115
|
+
} },
|
|
90
116
|
hasTitle && (React.createElement(Title, { title: titleProps, className: b('title'), colSizes: { all: 12 } })),
|
|
91
117
|
rowMode ? (React.createElement("div", { className: b('row-items') }, slots.map((slot, index) => {
|
|
92
118
|
const item = items[slot];
|
|
@@ -303,6 +303,8 @@ export interface LogoRotatorBlockProps extends Animatable {
|
|
|
303
303
|
isStatic?: boolean;
|
|
304
304
|
}[];
|
|
305
305
|
count: number;
|
|
306
|
+
minRotateCount?: number;
|
|
307
|
+
maxRotateCount?: number;
|
|
306
308
|
colSizes?: Partial<Record<GridColumnSize, number>>;
|
|
307
309
|
theme?: TextTheme;
|
|
308
310
|
rowMode?: boolean;
|