@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.
@@ -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 slotIndex = rotatableSlotIndices[Math.floor(Math.random() * rotatableSlotIndices.length)];
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
- next[slotIndex] = true;
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
- const available = rotatableIndices.filter((i) => !newSlots.includes(i));
65
- if (available.length > 0) {
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
- next[slotIndex] = false;
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];
@@ -185,6 +185,12 @@ export declare const LogoRotatorBlock: {
185
185
  count: {
186
186
  type: string;
187
187
  };
188
+ minRotateCount: {
189
+ type: string;
190
+ };
191
+ maxRotateCount: {
192
+ type: string;
193
+ };
188
194
  colSizes: {
189
195
  type: string;
190
196
  additionalProperties: {
@@ -29,6 +29,10 @@ exports.LogoRotatorBlock = {
29
29
  },
30
30
  }, count: {
31
31
  type: 'number',
32
+ }, minRotateCount: {
33
+ type: 'number',
34
+ }, maxRotateCount: {
35
+ type: 'number',
32
36
  }, colSizes: {
33
37
  type: 'object',
34
38
  additionalProperties: common_1.containerSizesObject,
@@ -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 slotIndex = rotatableSlotIndices[Math.floor(Math.random() * rotatableSlotIndices.length)];
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
- next[slotIndex] = true;
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
- const available = rotatableIndices.filter((i) => !newSlots.includes(i));
62
- if (available.length > 0) {
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
- next[slotIndex] = false;
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];
@@ -185,6 +185,12 @@ export declare const LogoRotatorBlock: {
185
185
  count: {
186
186
  type: string;
187
187
  };
188
+ minRotateCount: {
189
+ type: string;
190
+ };
191
+ maxRotateCount: {
192
+ type: string;
193
+ };
188
194
  colSizes: {
189
195
  type: string;
190
196
  additionalProperties: {
@@ -26,6 +26,10 @@ export const LogoRotatorBlock = {
26
26
  },
27
27
  }, count: {
28
28
  type: 'number',
29
+ }, minRotateCount: {
30
+ type: 'number',
31
+ }, maxRotateCount: {
32
+ type: 'number',
29
33
  }, colSizes: {
30
34
  type: 'object',
31
35
  additionalProperties: containerSizesObject,
@@ -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;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@doyourjob/gravity-ui-page-constructor",
3
- "version": "5.31.245",
3
+ "version": "5.31.246",
4
4
  "description": "Gravity UI Page Constructor",
5
5
  "license": "MIT",
6
6
  "repository": {